Compare commits

..

24 Commits

Author SHA1 Message Date
KimLS 79caacd8a3 Small util to connect to a login server and get dbid if user/pass matches. 2017-08-31 22:55:43 -07:00
KimLS 6a79694fa1 Merge branch 'master' of github.com:EQEmu/Server into wp 2017-08-31 17:47:33 -07:00
KimLS c52ff4249a Pathing stuck detection, and logic to go with it 2017-08-30 19:55:35 -07:00
KimLS 0ba9b3fedc Fix for bug in pathing stuck detection 2017-08-29 22:03:22 -07:00
KimLS 46561b9cf5 Factor in size to actor offset 2017-08-28 23:48:05 -07:00
KimLS 545ac6b420 Some pathing tweaks, removed old quest functions that dealt with the old pathing code. Fixes to best z under new system 2017-08-28 22:01:08 -07:00
KimLS 0e8f6a32b1 Explicit RTreeValue decl because gcc didnt like it implicitly here 2017-08-20 17:40:37 -07:00
KimLS 17544d4577 Some tweaks to GCC errors, still think there's a couple 2017-08-20 15:37:46 -07:00
KimLS 563878f20e Compile fixes and some debugging messages in find path code. 2017-08-19 12:49:06 -07:00
KimLS ffbee0ad1a Merge 2017-08-09 10:42:07 -07:00
KimLS 575ba28b62 Bug fixes with fear points and teleport jumps 2017-08-06 20:48:39 -07:00
KimLS 3afee1f841 Work on making the paths work well when being z corrected esp for nav meshes 2017-08-05 20:54:43 -07:00
KimLS 832c31a41a work on navmesh loading 2017-07-29 15:05:56 -07:00
KimLS ff13f162ce Forgot to git add so missed a bunch of stuff 2017-07-29 00:12:21 -07:00
KimLS 80f1c65e1c Update fmt lib, add recast, wip on recast pathfinder interface (broken atm) 2017-07-29 00:11:57 -07:00
KimLS 7d3f35d48b Support for v3 path files, removed the movement log stuff, fix for a crash or two 2017-07-27 23:21:45 -07:00
KimLS 69c6879ac9 Merge fix 2017-07-22 14:20:40 -07:00
KimLS bdc90ac3a7 Command changes and code cleanup 2017-07-21 20:22:33 -07:00
KimLS ab33148f81 Some tweaks to wp, basically works 2017-07-20 00:34:58 -07:00
KimLS c2766db89d Working on waypoint code, using boost graph libs 2017-07-19 19:54:26 -07:00
KimLS 5f1063acb9 Add pathfinding interfaces, still heavily wip 2017-07-18 00:01:59 -07:00
KimLS 596e3b28b5 Actually add the interface files 2017-07-16 22:30:19 -07:00
KimLS 077ba02004 Merge branch 'master' of github.com:EQEmu/Server into wp 2017-07-16 22:30:03 -07:00
KimLS 75ee3b30e2 Support for races up to waypoint node race, wip on interface for pathfinding to support both kinds. 2017-07-16 22:29:52 -07:00
358 changed files with 35664 additions and 33101 deletions
+10 -17
View File
@@ -23,24 +23,17 @@ CMakeFiles
Makefile
cmake_install.cmake
install_manifest.txt
[Bb]uild/
[Bb]uild32/
[Bb]uild64/
[Bb]uild_32/
[Bb]uild_64/
deploy/server/
Build/
build/
Build32/
build32/
Build64/
build64/
Build_32/
build_32/
Build_64/
build_64/
x64/
x86/
log/
logs/
docker/db
# Protobuf generated files
*.pb.cc
*.pb.h
protobuf/csharp/*
protobuf/go/*
protobuf/java/*
protobuf/python/*
.vscode
+11 -77
View File
@@ -29,7 +29,7 @@
#We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
#Can change this if you really want but you should upgrade!
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#FindMySQL is located here so lets make it so CMake can find it
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -52,73 +52,6 @@ IF(MSVC OR MINGW)
ENDIF(CMAKE_CL_64)
ENDIF(MSVC OR MINGW)
# include dirs are universal
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats")
#Try to find protobuf automatically
FIND_PACKAGE(Protobuf QUIET)
#IF(NOT PROTOBUF_FOUND)
SET(Protobuf_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/protobuf" CACHE PATH "Root protobuf directory" FORCE)
SET(PROTOBUF_FOUND TRUE CACHE BOOL "" FORCE)
IF(MSVC)
IF(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/windows/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/windows/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/windows/x64/bin/protoc.exe" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/windows/x64/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/windows/x64/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
ELSE(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/windows/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/windows/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/windows/x86/bin/protoc.exe" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/windows/x86/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/windows/x86/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
ENDIF(CMAKE_CL_64)
ELSE(MSVC)
IF(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/linux/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/linux/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/linux/x86/bin/protoc" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/linux/x86/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/linux/x86/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
ELSE(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/linux/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/linux/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/linux/x64/bin/protoc" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/linux/x64/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/linux/x64/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
ENDIF(CMAKE_CL_64)
ENDIF()
IF(NOT Protobuf_LIBRARY_DEBUG)
MESSAGE(ERROR "Protobuf library was not found in ${Protobuf_LIBRARY_DEBUG}. Please download the depenencies and extract them as noted.")
ENDIF()
FILE(COPY ${Protobuf_LIBRARY_DEBUG} DESTINATION ${CMAKE_HOME_DIRECTORY}/bin)
#ENDIF()
INCLUDE_DIRECTORIES(SYSTEM "${Protobuf_INCLUDE_DIR}")
IF(MSVC)
IF(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/windows/x64/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/windows/x64/lib/nats.lib")
ELSE(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/windows/x86/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/windows/x86/lib/nats.lib")
ENDIF(CMAKE_CL_64)
ELSE(MSVC)
IF(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/linux/x86/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/linux/x86/lib/libnats.so")
ELSE(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/linux/x64/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/linux/x64/lib/libnats.so")
ENDIF(CMAKE_CL_64)
ENDIF()
IF(${NATS_LIBRARY_DEBUG})
MESSAGE(ERROR " NATS library was not found in ${NATS_LIBRARY_DEBUG}/libnats.so. Please download the depenencies and extract them as noted.")
ENDIF()
FILE(COPY ${NATS_LIBRARY_DEBUG} DESTINATION ${CMAKE_HOME_DIRECTORY}/bin)
IF(MSVC)
#Set our default locations for zlib/mysql based on x86/x64
IF(CMAKE_CL_64)
@@ -140,7 +73,6 @@ IF(MSVC)
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats_x86")
IF(MSVC_VERSION GREATER 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
ELSEIF(MSVC_VERSION EQUAL 1800)
@@ -199,8 +131,6 @@ IF(MSVC)
ADD_DEFINITIONS(-DNOMINMAX)
ELSE(MSVC)
#Normally set by perl but we don't use the perl flags anymore so we set it.
ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC)
@@ -329,6 +259,7 @@ ENDIF(EQEMU_ENABLE_BOTS)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_LOGIN "Build the login server." 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_PERL "Build Perl parser." ON)
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
@@ -379,7 +310,7 @@ IF(EQEMU_BUILD_PERL)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
ENDIF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt ${NATS_LIBRARY_DEBUG} ${PROTOBUF_LIBRARY_DEBUG})
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt recast_navigation)
FIND_PACKAGE(Sodium REQUIRED)
IF(SODIUM_FOUND)
@@ -422,19 +353,18 @@ ENDIF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${NATS_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/format")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/detour/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/recast/include")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
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(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)
ADD_SUBDIRECTORY(shared_memory)
ADD_SUBDIRECTORY(world)
@@ -451,6 +381,10 @@ IF(EQEMU_BUILD_HC)
ADD_SUBDIRECTORY(hc)
ENDIF(EQEMU_BUILD_HC)
IF(EQEMU_BUILD_LP)
ADD_SUBDIRECTORY(lp)
ENDIF(EQEMU_BUILD_LP)
IF(EQEMU_BUILD_TESTS)
ADD_SUBDIRECTORY(tests)
ENDIF(EQEMU_BUILD_TESTS)
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
-165
View File
@@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+12
View File
@@ -0,0 +1,12 @@
The server code and utilities are released under GPLv3.
We also include some small libraries for convienence that may be under different licensing:
SocketLib - GPL
LibXML - ZLib License
StackWalker - New BSD License
ZLib - ZLib License
MySQL - GPL
Perl - GPL / ActiveState (under the assumption that this is a free project).
CPPUnit - GLP
StringUtilities - Apache
+7 -20
View File
@@ -17,7 +17,10 @@
|:---:|:---:|:---:|
|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)|
### > Windows
* [Install](https://github.com/EQEmu/Server/wiki/Windows-Server)
* [Easy Install](http://wiki.eqemulator.org/p?Akkas_PEQ_Server_Installer&frm=Main#from-scratch-installation-instructions-windows)
* [Advanced Setup](http://wiki.eqemulator.org/p?Complete_Windows-based_Server_Setup_Guide)
### > Debian/Ubuntu/CentOS/Fedora
* You can use curl or wget to kick off the installer (whichever your OS has)
@@ -50,23 +53,7 @@ forum, although pull requests will be much quicker and easier on all parties.
- **User Discord Channel**: `#general`
- **Developer Discord Channel**: `#eqemucoders`
## Resources
Resources
---
- [EQEmulator Forums](http://www.eqemulator.org/forums)
- [EQEmulator Wiki](https://github.com/EQEmu/Server/wiki)
## Related Repositories
* [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests)
* [Maps](https://github.com/Akkadius/EQEmuMaps)
* [Installer Resources](https://github.com/Akkadius/EQEmuInstall)
* [Zone Utilities](https://github.com/EQEmu/zone-utilities) - Various utilities and libraries for parsing, rendering and manipulating EQ Zone files.
## Other License Info
* The server code and utilities are released under **GPLv3**
* We also include some small libraries for convienence that may be under different licensing
* SocketLib - GPL LibXML
* zlib - zlib license
* MariaDB/MySQL - GPL
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
* CPPUnit - GLP StringUtilities - Apache
* LUA - MIT
- [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki)
-85
View File
@@ -1,90 +1,5 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 03/07/2018 ==
Uleat: Added command '#ucs' to force a reconnect to UCS server.
- Works in place of client auto-reconnect packet in zones where feature is unsupported
- Currently, you will need to manually re-join channels
== 03/04/2018 ==
Uleat: Updated UCS versioning
- SoF and higher clients have a new opcode identified (update your *.conf files)
- Rework of previous ucs connectivity code
- Unrelated: Zone::weatherSend() now takes an optional parameter for singular updates (as in client entering zone)
-- prior to this, every client already in-zone received a weather update packet whenever a new client zoned in
== 02/18/2018 ==
Uleat: Bug reporting fix and overhaul.
- Fixed bug reporting for SoD+ clients
- Added ability to disable bug reporting (set rule 'Bugs:ReportingSystemActive' to 'false')
- Implemented a more detailed reporting system (set rule 'Bugs:UseOldReportingMethod' to 'false')
-- New system is not currently compatible with script-based monitoring
- Soft-removal of defunct 'Petition Bug' system
== 02/14/2018 ==
mackal: Fix Heading -- Quests broken
Please report any other issues with heading, most things were tested and worked
You can use eqemu_server.pl to run a conversion to fix your headings in quests.
Some may need manual review.
== 02/10/2018 ==
mackal: Add Global Loot system
This will allow us to implement global loot similarly to how it works on live
This system reuses our current loottable tables which the global_loot table references.
The limits for the rules to govern if a table should be rolled are min level, max level, rare,
raid, race, class, bodytype, and zone
race, class, bodytype, and zone are a pipe | separated list of IDs.
== 01/31/2018 ==
Uleat: Re-work of Bot::AI_Process(). Overall behavior is much improved.
- Removed a 'ton' of unneeded packet updates
- Added a 'leash' to the distance a bot can travel
- Added a 'main assist' feature to target control (set using group roles)
- Added combat 'jitter' movement to complement the existing rogue movement
- Attack can now be aborted if target contains no leash owner nor bot hate and leash owner turns off auto-attack
- Please report any issues with the bot AI code
Added a work-around for heal rotations crashing the server - under certain conditions.
== 01/28/2018 ==
Mackal: Spell AI tweaks
AI spells are treated as "innate" spells (devs use this term, and I think this is what they mean by it)
These spells are spammed by the NPC, lots of encounters on live work like this and this will greatly reduce
the need to do quest scripting on these types of encounters.
You can safely run update npc_spells_entries set priority = priority + 1 where priority >= 0; if you want to disable this new behavior
== 10/08/2017 ==
Mackal: Rework regens
Regen will now match whats reported by modern clients, besides where they lie due to known bugs
HP and END regens are now based on the BaseData.txt values allowing easy customization
Those cases:
- The client always applies hunger penalties, it appears they don't exist anymore on live you can turn them on with a rule
- The way the client gets buff mana/end regen benefits incorrectly applies the bard mod making these values lie sometimes
== 9/17/2017 ==
Akkadius: Add model/race offset to FixZ calc (KLS)
Akkadius: Fix 95% of food/water consumption issues, if there are additional modifiers for race/class combos - those will need to be applied
Stages should be put in place if not already:
https://wiki.project1999.com/Food_and_drink#Stages_of_Hunger_and_Thirst
Values stored in the database are 0-6000, previously we capped it at 6000 but previous math would have normal values in the 60k+ range in order for food to be consumed at a reasonable rate. We are now using more native logic where 1 = 1 minute, following logic:
(Minutes)
0 - 5 - This is a snack.
6 - 20 - This is a meal.
21 - 30 - This is a hearty meal.
31 - 40 - This is a banquet size meal.
41 - 50 - This meal is a feast!
51 - 60 - This is an enduring meal!
61 - X - This is a miraculous meal!
== 7/14/2017 ==
Akkadius: HP Update tuning - HP Updates are now forced when a client is targeted
-386
View File
@@ -1,386 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindPackageHandleStandardArgs
-----------------------------
This module provides a function intended to be used in :ref:`Find Modules`
implementing :command:`find_package(<PackageName>)` calls. It handles the
``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``.
It also sets the ``<PackageName>_FOUND`` variable. The package is
considered found if all variables listed contain valid results, e.g.
valid filepaths.
.. command:: find_package_handle_standard_args
There are two signatures::
find_package_handle_standard_args(<PackageName>
(DEFAULT_MSG|<custom-failure-message>)
<required-var>...
)
find_package_handle_standard_args(<PackageName>
[FOUND_VAR <result-var>]
[REQUIRED_VARS <required-var>...]
[VERSION_VAR <version-var>]
[HANDLE_COMPONENTS]
[CONFIG_MODE]
[FAIL_MESSAGE <custom-failure-message>]
)
The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
the variables ``<required-var>...`` are valid and any optional
constraints are satisfied, and ``FALSE`` otherwise. A success or
failure message may be displayed based on the results and on
whether the ``REQUIRED`` and/or ``QUIET`` option was given to
the :command:`find_package` call.
The options are:
``(DEFAULT_MSG|<custom-failure-message>)``
In the simple signature this specifies the failure message.
Use ``DEFAULT_MSG`` to ask for a default message to be computed
(recommended). Not valid in the full signature.
``FOUND_VAR <result-var>``
Obsolete. Specifies either ``<PackageName>_FOUND`` or
``<PACKAGENAME>_FOUND`` as the result variable. This exists only
for compatibility with older versions of CMake and is now ignored.
Result variables of both names are always set for compatibility.
``REQUIRED_VARS <required-var>...``
Specify the variables which are required for this package.
These may be named in the generated failure message asking the
user to set the missing variable values. Therefore these should
typically be cache entries such as ``FOO_LIBRARY`` and not output
variables like ``FOO_LIBRARIES``.
``VERSION_VAR <version-var>``
Specify the name of a variable that holds the version of the package
that has been found. This version will be checked against the
(potentially) specified required version given to the
:command:`find_package` call, including its ``EXACT`` option.
The default messages include information about the required
version and the version which has been actually found, both
if the version is ok or not.
``HANDLE_COMPONENTS``
Enable handling of package components. In this case, the command
will report which components have been found and which are missing,
and the ``<PackageName>_FOUND`` variable will be set to ``FALSE``
if any of the required components (i.e. not the ones listed after
the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are
missing.
``CONFIG_MODE``
Specify that the calling find module is a wrapper around a
call to ``find_package(<PackageName> NO_MODULE)``. This implies
a ``VERSION_VAR`` value of ``<PackageName>_VERSION``. The command
will automatically check whether the package configuration file
was found.
``FAIL_MESSAGE <custom-failure-message>``
Specify a custom failure message instead of using the default
generated message. Not recommended.
Example for the simple signature:
.. code-block:: cmake
find_package_handle_standard_args(LibXml2 DEFAULT_MSG
LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
The ``LibXml2`` package is considered to be found if both
``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found
and ``REQUIRED`` was used, it fails with a
:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
used or not. If it is found, success will be reported, including
the content of the first ``<required-var>``. On repeated CMake runs,
the same message will not be printed again.
Example for the full signature:
.. code-block:: cmake
find_package_handle_standard_args(LibArchive
REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
VERSION_VAR LibArchive_VERSION)
In this case, the ``LibArchive`` package is considered to be found if
both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
Also the version of ``LibArchive`` will be checked by using the version
contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given,
the default messages will be printed.
Another example for the full signature:
.. code-block:: cmake
find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
find_package_handle_standard_args(Automoc4 CONFIG_MODE)
In this case, a ``FindAutmoc4.cmake`` module wraps a call to
``find_package(Automoc4 NO_MODULE)`` and adds an additional search
directory for ``automoc4``. Then the call to
``find_package_handle_standard_args`` produces a proper success/failure
message.
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_msg}")
endif ()
endif ()
endmacro()
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
if(${_NAME}_CONFIG)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
else()
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
# List them all in the error message:
if(${_NAME}_CONSIDERED_CONFIGS)
set(configsText "")
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
math(EXPR configsCount "${configsCount} - 1")
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
string(APPEND configsText " ${filename} (version ${version})\n")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
string(APPEND configsText " Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
# Simple case: No Config-file was found at all:
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
endif()
endif()
endmacro()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS)
set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
# Check whether we are in 'simple' or 'extended' mode:
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
endif()
if(NOT FPHSA_REQUIRED_VARS)
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
endif()
endif()
# now that we collected all arguments, process them
if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
string(TOUPPER ${_NAME} _NAME_UPPER)
string(TOLOWER ${_NAME} _NAME_LOWER)
if(FPHSA_FOUND_VAR)
if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
set(_FOUND_VAR ${FPHSA_FOUND_VAR})
else()
message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
endif()
else()
set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
endif()
# collect all variables which were not found, so they can be printed, so the
# user knows better what went wrong (#6375)
set(MISSING_VARS "")
set(DETAILS "")
# check if all passed variables are valid
set(FPHSA_FOUND_${_NAME} TRUE)
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
if(NOT ${_CURRENT_VAR})
set(FPHSA_FOUND_${_NAME} FALSE)
string(APPEND MISSING_VARS " ${_CURRENT_VAR}")
else()
string(APPEND DETAILS "[${${_CURRENT_VAR}}]")
endif()
endforeach()
if(FPHSA_FOUND_${_NAME})
set(${_NAME}_FOUND TRUE)
set(${_NAME_UPPER}_FOUND TRUE)
else()
set(${_NAME}_FOUND FALSE)
set(${_NAME_UPPER}_FOUND FALSE)
endif()
# component handling
unset(FOUND_COMPONENTS_MSG)
unset(MISSING_COMPONENTS_MSG)
if(FPHSA_HANDLE_COMPONENTS)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(${_NAME}_${comp}_FOUND)
if(NOT DEFINED FOUND_COMPONENTS_MSG)
set(FOUND_COMPONENTS_MSG "found components: ")
endif()
string(APPEND FOUND_COMPONENTS_MSG " ${comp}")
else()
if(NOT DEFINED MISSING_COMPONENTS_MSG)
set(MISSING_COMPONENTS_MSG "missing components: ")
endif()
string(APPEND MISSING_COMPONENTS_MSG " ${comp}")
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
string(APPEND MISSING_VARS " ${comp}")
endif()
endif()
endforeach()
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
string(APPEND DETAILS "[c${COMPONENT_MSG}]")
endif()
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
# check with DEFINED here as the requested or found version may be "0"
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
# count the dots in the version string
string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${_FOUND_VERSION}")
# add one dot because there is one dot more than there are components
string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
# Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
# is at most 4 here. Therefore a simple lookup table is used.
if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
set(_VERSION_REGEX "[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
set(_VERSION_REGEX "[^.]*\\.[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
else ()
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
endif ()
string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${_FOUND_VERSION}")
unset(_VERSION_REGEX)
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
unset(_VERSION_HEAD)
else ()
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _FOUND_VERSION)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
endif ()
unset(_VERSION_DOTS)
else() # minimum version specified:
if (${_NAME}_FIND_VERSION VERSION_GREATER _FOUND_VERSION)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable version \"${_FOUND_VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
endif ()
endif()
else()
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
else()
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
endif()
endif()
else ()
# Check with DEFINED as the found version may be 0.
if(DEFINED ${FPHSA_VERSION_VAR})
set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")")
endif()
endif ()
if(VERSION_OK)
string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]")
else()
set(${_NAME}_FOUND FALSE)
endif()
# print the result:
if (${_NAME}_FOUND)
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
else ()
if(FPHSA_CONFIG_MODE)
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
else()
if(NOT VERSION_OK)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
else()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}")
endif()
endif()
endif ()
set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
endfunction()
-47
View File
@@ -1,47 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindPackageMessage
# ------------------
#
#
#
# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details")
#
# This macro is intended to be used in FindXXX.cmake modules files. It
# will print a message once for each unique find result. This is useful
# for telling the user where a package was found. The first argument
# specifies the name (XXX) of the package. The second argument
# specifies the message to display. The third argument lists details
# about the find result so that if they change the message will be
# displayed again. The macro also obeys the QUIET argument to the
# find_package command.
#
# Example:
#
# ::
#
# if(X11_FOUND)
# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
# else()
# ...
# endif()
function(FIND_PACKAGE_MESSAGE pkg msg details)
# Avoid printing a message repeatedly for the same find result.
if(NOT ${pkg}_FIND_QUIETLY)
string(REPLACE "\n" "" details "${details}")
set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
# The message has not yet been printed.
message(STATUS "${msg}")
# Save the find details in the cache to avoid printing the same
# message again.
set("${DETAILS_VAR}" "${details}"
CACHE INTERNAL "Details about finding ${pkg}")
endif()
endif()
endfunction()
-579
View File
@@ -1,579 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindProtobuf
# ------------
#
# Locate and configure the Google Protocol Buffers library.
#
# The following variables can be set and are optional:
#
# ``Protobuf_SRC_ROOT_FOLDER``
# When compiling with MSVC, if this cache variable is set
# the protobuf-default VS project build locations
# (vsprojects/Debug and vsprojects/Release
# or vsprojects/x64/Debug and vsprojects/x64/Release)
# will be searched for libraries and binaries.
# ``Protobuf_IMPORT_DIRS``
# List of additional directories to be searched for
# imported .proto files.
# ``Protobuf_DEBUG``
# Show debug messages.
# ``Protobuf_USE_STATIC_LIBS``
# Set to ON to force the use of the static libraries.
# Default is OFF.
#
# Defines the following variables:
#
# ``Protobuf_FOUND``
# Found the Google Protocol Buffers library
# (libprotobuf & header files)
# ``Protobuf_VERSION``
# Version of package found.
# ``Protobuf_INCLUDE_DIRS``
# Include directories for Google Protocol Buffers
# ``Protobuf_LIBRARIES``
# The protobuf libraries
# ``Protobuf_PROTOC_LIBRARIES``
# The protoc libraries
# ``Protobuf_LITE_LIBRARIES``
# The protobuf-lite libraries
#
# The following :prop_tgt:`IMPORTED` targets are also defined:
#
# ``protobuf::libprotobuf``
# The protobuf library.
# ``protobuf::libprotobuf-lite``
# The protobuf lite library.
# ``protobuf::libprotoc``
# The protoc library.
# ``protobuf::protoc``
# The protoc compiler.
#
# The following cache variables are also available to set or use:
#
# ``Protobuf_LIBRARY``
# The protobuf library
# ``Protobuf_PROTOC_LIBRARY``
# The protoc library
# ``Protobuf_INCLUDE_DIR``
# The include directory for protocol buffers
# ``Protobuf_PROTOC_EXECUTABLE``
# The protoc compiler
# ``Protobuf_LIBRARY_DEBUG``
# The protobuf library (debug)
# ``Protobuf_PROTOC_LIBRARY_DEBUG``
# The protoc library (debug)
# ``Protobuf_LITE_LIBRARY``
# The protobuf lite library
# ``Protobuf_LITE_LIBRARY_DEBUG``
# The protobuf lite library (debug)
#
# Example:
#
# .. code-block:: cmake
#
# find_package(Protobuf REQUIRED)
# include_directories(${Protobuf_INCLUDE_DIRS})
# include_directories(${CMAKE_CURRENT_BINARY_DIR})
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS DESCRIPTORS PROTO_DESCS foo.proto)
# protobuf_generate_python(PROTO_PY foo.proto)
# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
# target_link_libraries(bar ${Protobuf_LIBRARIES})
#
# .. note::
# The ``protobuf_generate_cpp`` and ``protobuf_generate_python``
# functions and :command:`add_executable` or :command:`add_library`
# calls only work properly within the same directory.
#
# .. command:: protobuf_generate_cpp
#
# Add custom commands to process ``.proto`` files to C++::
#
# protobuf_generate_cpp (<SRCS> <HDRS>
# [DESCRIPTORS <DESC>] [EXPORT_MACRO <MACRO>] [<ARGN>...])
#
# ``SRCS``
# Variable to define with autogenerated source files
# ``HDRS``
# Variable to define with autogenerated header files
# ``DESCRIPTORS``
# Variable to define with autogenerated descriptor files, if requested.
# ``EXPORT_MACRO``
# is a macro which should expand to ``__declspec(dllexport)`` or
# ``__declspec(dllimport)`` depending on what is being compiled.
# ``ARGN``
# ``.proto`` files
#
# .. command:: protobuf_generate_python
#
# Add custom commands to process ``.proto`` files to Python::
#
# protobuf_generate_python (<PY> [<ARGN>...])
#
# ``PY``
# Variable to define with autogenerated Python files
# ``ARGN``
# ``.proto`` filess
function(PROTOBUF_GENERATE_CPP SRCS HDRS)
cmake_parse_arguments(protobuf "" "EXPORT_MACRO;DESCRIPTORS" "" ${ARGN})
set(PROTO_FILES "${protobuf_UNPARSED_ARGUMENTS}")
if(NOT PROTO_FILES)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif()
if(protobuf_EXPORT_MACRO)
set(DLL_EXPORT_DECL "dllexport_decl=${protobuf_EXPORT_MACRO}:")
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${PROTO_FILES})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
endif()
if(DEFINED Protobuf_IMPORT_DIRS)
foreach(DIR ${Protobuf_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
set(${SRCS})
set(${HDRS})
if (protobuf_DESCRIPTORS)
set(${protobuf_DESCRIPTORS})
endif()
foreach(FIL ${PROTO_FILES})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
if(FIL_DIR)
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
endif()
endif()
set(_protobuf_protoc_src "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.pb.cc")
set(_protobuf_protoc_hdr "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.pb.h")
list(APPEND ${SRCS} "${_protobuf_protoc_src}")
list(APPEND ${HDRS} "${_protobuf_protoc_hdr}")
if(protobuf_DESCRIPTORS)
set(_protobuf_protoc_desc "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.desc")
set(_protobuf_protoc_flags "--descriptor_set_out=${_protobuf_protoc_desc}")
list(APPEND ${protobuf_DESCRIPTORS} "${_protobuf_protoc_desc}")
else()
set(_protobuf_protoc_desc "")
set(_protobuf_protoc_flags "")
endif()
add_custom_command(
OUTPUT "${_protobuf_protoc_src}"
"${_protobuf_protoc_hdr}"
${_protobuf_protoc_desc}
COMMAND protobuf::protoc
"--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_SOURCE_DIR}"
${_protobuf_protoc_flags}
${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} protobuf::protoc
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
set(${SRCS} "${${SRCS}}" PARENT_SCOPE)
set(${HDRS} "${${HDRS}}" PARENT_SCOPE)
if(protobuf_DESCRIPTORS)
set(${protobuf_DESCRIPTORS} "${${protobuf_DESCRIPTORS}}" PARENT_SCOPE)
endif()
endfunction()
function(PROTOBUF_GENERATE_PYTHON SRCS)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
return()
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
endif()
if(DEFINED Protobuf_IMPORT_DIRS)
foreach(DIR ${Protobuf_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
set(${SRCS})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
if(FIL_DIR)
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
endif()
endif()
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
COMMAND protobuf::protoc --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} protobuf::protoc
COMMENT "Running Python protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
endfunction()
if(Protobuf_DEBUG)
# Output some of their choices
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}")
endif()
# Backwards compatibility
# Define camel case versions of input variables
foreach(UPPER
PROTOBUF_SRC_ROOT_FOLDER
PROTOBUF_IMPORT_DIRS
PROTOBUF_DEBUG
PROTOBUF_LIBRARY
PROTOBUF_PROTOC_LIBRARY
PROTOBUF_INCLUDE_DIR
PROTOBUF_PROTOC_EXECUTABLE
PROTOBUF_LIBRARY_DEBUG
PROTOBUF_PROTOC_LIBRARY_DEBUG
PROTOBUF_LITE_LIBRARY
PROTOBUF_LITE_LIBRARY_DEBUG
)
if (DEFINED ${UPPER})
string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
if (NOT DEFINED ${Camel})
set(${Camel} ${${UPPER}})
endif()
endif()
endforeach()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_PROTOBUF_ARCH_DIR x64/)
endif()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
if( Protobuf_USE_STATIC_LIBS )
set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
endif()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
# Internal function: search for normal library as well as a debug one
# if the debug one is specified also include debug/optimized keywords
# in *_LIBRARIES variable
function(_protobuf_find_libraries name filename)
if(${name}_LIBRARIES)
# Use result recorded by a previous call.
return()
elseif(${name}_LIBRARY)
# Honor cache entry used by CMake 3.5 and lower.
set(${name}_LIBRARIES "${${name}_LIBRARY}" PARENT_SCOPE)
else()
find_library(${name}_LIBRARY_RELEASE
NAMES ${filename}
PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release)
mark_as_advanced(${name}_LIBRARY_RELEASE)
find_library(${name}_LIBRARY_DEBUG
NAMES ${filename}d ${filename}
PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug)
mark_as_advanced(${name}_LIBRARY_DEBUG)
select_library_configurations(${name})
set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
set(${name}_LIBRARIES "${${name}_LIBRARIES}" PARENT_SCOPE)
endif()
endfunction()
# Internal function: find threads library
function(_protobuf_find_threads)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads)
if(Threads_FOUND)
list(APPEND Protobuf_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
set(Protobuf_LIBRARIES "${Protobuf_LIBRARIES}" PARENT_SCOPE)
endif()
endfunction()
#
# Main.
#
# By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
# for each directory where a proto file is referenced.
if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
endif()
# Google's provided vcproj files generate libraries with a "lib"
# prefix on Windows
if(MSVC)
set(Protobuf_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
find_path(Protobuf_SRC_ROOT_FOLDER protobuf.pc.in)
endif()
# The Protobuf library
_protobuf_find_libraries(Protobuf protobuf)
#DOC "The Google Protocol Buffers RELEASE Library"
_protobuf_find_libraries(Protobuf_LITE protobuf-lite)
# The Protobuf Protoc Library
_protobuf_find_libraries(Protobuf_PROTOC protoc)
# Restore original find library prefixes
if(MSVC)
set(CMAKE_FIND_LIBRARY_PREFIXES "${Protobuf_ORIG_FIND_LIBRARY_PREFIXES}")
endif()
if(UNIX)
_protobuf_find_threads()
endif()
# Find the include directory
find_path(Protobuf_INCLUDE_DIR
google/protobuf/service.h
PATHS ${Protobuf_SRC_ROOT_FOLDER}/src
)
mark_as_advanced(Protobuf_INCLUDE_DIR)
# Find the protoc Executable
find_program(Protobuf_PROTOC_EXECUTABLE
NAMES protoc
DOC "The Google Protocol Buffers Compiler"
PATHS /usr/bin
${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release
${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug
)
mark_as_advanced(Protobuf_PROTOC_EXECUTABLE)
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"requested version of Google Protobuf is ${Protobuf_FIND_VERSION}")
endif()
if(Protobuf_INCLUDE_DIR)
set(_PROTOBUF_COMMON_HEADER ${Protobuf_INCLUDE_DIR}/google/protobuf/stubs/common.h)
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"location of common.h: ${_PROTOBUF_COMMON_HEADER}")
endif()
set(Protobuf_VERSION "")
set(Protobuf_LIB_VERSION "")
file(STRINGS ${_PROTOBUF_COMMON_HEADER} _PROTOBUF_COMMON_H_CONTENTS REGEX "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+")
if(_PROTOBUF_COMMON_H_CONTENTS MATCHES "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+([0-9]+)")
set(Protobuf_LIB_VERSION "${CMAKE_MATCH_1}")
endif()
unset(_PROTOBUF_COMMON_H_CONTENTS)
math(EXPR _PROTOBUF_MAJOR_VERSION "${Protobuf_LIB_VERSION} / 1000000")
math(EXPR _PROTOBUF_MINOR_VERSION "${Protobuf_LIB_VERSION} / 1000 % 1000")
math(EXPR _PROTOBUF_SUBMINOR_VERSION "${Protobuf_LIB_VERSION} % 1000")
set(Protobuf_VERSION "${_PROTOBUF_MAJOR_VERSION}.${_PROTOBUF_MINOR_VERSION}.${_PROTOBUF_SUBMINOR_VERSION}")
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"${_PROTOBUF_COMMON_HEADER} reveals protobuf ${Protobuf_VERSION}")
endif()
# Check Protobuf compiler version to be aligned with libraries version
execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} --version
OUTPUT_VARIABLE _PROTOBUF_PROTOC_EXECUTABLE_VERSION)
if("${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" MATCHES "libprotoc ([0-9.]+)")
set(_PROTOBUF_PROTOC_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
endif()
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"${Protobuf_PROTOC_EXECUTABLE} reveals version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}")
endif()
if(NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${Protobuf_VERSION}")
message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}"
" doesn't match library version ${Protobuf_VERSION}")
endif()
if(Protobuf_LIBRARY)
if(NOT TARGET protobuf::libprotobuf)
add_library(protobuf::libprotobuf UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotobuf PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_LIBRARY}")
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION "${Protobuf_LIBRARY}")
endif()
if(EXISTS "${Protobuf_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_LITE_LIBRARY)
if(NOT TARGET protobuf::libprotobuf-lite)
add_library(protobuf::libprotobuf-lite UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_LITE_LIBRARY}")
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION "${Protobuf_LITE_LIBRARY}")
endif()
if(EXISTS "${Protobuf_LITE_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_LITE_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_LITE_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_PROTOC_LIBRARY)
if(NOT TARGET protobuf::libprotoc)
add_library(protobuf::libprotoc UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotoc PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_PROTOC_LIBRARY}")
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}")
endif()
if(EXISTS "${Protobuf_PROTOC_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotoc APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_PROTOC_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotoc APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_PROTOC_EXECUTABLE)
if(NOT TARGET protobuf::protoc)
add_executable(protobuf::protoc IMPORTED)
if(EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
set_target_properties(protobuf::protoc PROPERTIES
IMPORTED_LOCATION "${Protobuf_PROTOC_EXECUTABLE}")
endif()
endif()
endif()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Protobuf
REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIR
VERSION_VAR Protobuf_VERSION
)
if(Protobuf_FOUND)
set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR})
endif()
# Restore the original find library ordering
if( Protobuf_USE_STATIC_LIBS )
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
# Backwards compatibility
# Define upper case versions of output variables
foreach(Camel
Protobuf_SRC_ROOT_FOLDER
Protobuf_IMPORT_DIRS
Protobuf_DEBUG
Protobuf_INCLUDE_DIRS
Protobuf_LIBRARIES
Protobuf_PROTOC_LIBRARIES
Protobuf_LITE_LIBRARIES
Protobuf_LIBRARY
Protobuf_PROTOC_LIBRARY
Protobuf_INCLUDE_DIR
Protobuf_PROTOC_EXECUTABLE
Protobuf_LIBRARY_DEBUG
Protobuf_PROTOC_LIBRARY_DEBUG
Protobuf_LITE_LIBRARY
Protobuf_LITE_LIBRARY_DEBUG
)
string(TOUPPER ${Camel} UPPER)
set(${UPPER} ${${Camel}})
endforeach()
-71
View File
@@ -1,71 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# SelectLibraryConfigurations
# ---------------------------
#
#
#
# select_library_configurations( basename )
#
# This macro takes a library base name as an argument, and will choose
# good values for basename_LIBRARY, basename_LIBRARIES,
# basename_LIBRARY_DEBUG, and basename_LIBRARY_RELEASE depending on what
# has been found and set. If only basename_LIBRARY_RELEASE is defined,
# basename_LIBRARY will be set to the release value, and
# basename_LIBRARY_DEBUG will be set to basename_LIBRARY_DEBUG-NOTFOUND.
# If only basename_LIBRARY_DEBUG is defined, then basename_LIBRARY will
# take the debug value, and basename_LIBRARY_RELEASE will be set to
# basename_LIBRARY_RELEASE-NOTFOUND.
#
# If the generator supports configuration types, then basename_LIBRARY
# and basename_LIBRARIES will be set with debug and optimized flags
# specifying the library to be used for the given configuration. If no
# build type has been set or the generator in use does not support
# configuration types, then basename_LIBRARY and basename_LIBRARIES will
# take only the release value, or the debug value if the release one is
# not set.
# This macro was adapted from the FindQt4 CMake module and is maintained by Will
# Dicharry <wdicharry@stellarscience.com>.
macro( select_library_configurations basename )
if(NOT ${basename}_LIBRARY_RELEASE)
set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.")
endif()
if(NOT ${basename}_LIBRARY_DEBUG)
set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.")
endif()
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND
NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND
( _isMultiConfig OR CMAKE_BUILD_TYPE ) )
# if the generator is multi-config or if CMAKE_BUILD_TYPE is set for
# single-config generators, set optimized and debug libraries
set( ${basename}_LIBRARY "" )
foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE )
list( APPEND ${basename}_LIBRARY optimized "${_libname}" )
endforeach()
foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG )
list( APPEND ${basename}_LIBRARY debug "${_libname}" )
endforeach()
elseif( ${basename}_LIBRARY_RELEASE )
set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} )
elseif( ${basename}_LIBRARY_DEBUG )
set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} )
else()
set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND")
endif()
set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" )
if( ${basename}_LIBRARY )
set( ${basename}_FOUND TRUE )
endif()
mark_as_advanced( ${basename}_LIBRARY_RELEASE
${basename}_LIBRARY_DEBUG
)
endmacro()
+4 -7
View File
@@ -1,11 +1,9 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(PROTOBUF_GENERATE_CPP_APPEND_PATH "../../")
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HEADERS message.proto)
SET(common_sources
base_packet.cpp
classes.cpp
compression.cpp
condition.cpp
crash.cpp
crc16.cpp
@@ -42,10 +40,9 @@ SET(common_sources
item_instance.cpp
json_config.cpp
light_source.cpp
md5.cpp
md5.cpp
memory_buffer.cpp
memory_mapped_file.cpp
message.pb.cc
misc.cpp
misc_functions.cpp
mutex.cpp
@@ -101,7 +98,7 @@ SET(common_sources
patches/titanium.cpp
patches/titanium_limits.cpp
patches/uf.cpp
patches/uf_limits.cpp
patches/uf_limits.cpp
StackWalker/StackWalker.cpp
tinyxml/tinystr.cpp
tinyxml/tinyxml.cpp
@@ -117,6 +114,7 @@ SET(common_headers
base_data.h
bodytypes.h
classes.h
compression.h
condition.h
crash.h
crc16.h
@@ -171,7 +169,6 @@ SET(common_headers
md5.h
memory_buffer.h
memory_mapped_file.h
message.pb.h
misc.h
misc_functions.h
mutex.h
+2 -2
View File
@@ -24,8 +24,8 @@ struct BaseDataStruct
double base_hp;
double base_mana;
double base_end;
double hp_regen;
double end_regen;
double unk1;
double unk2;
double hp_factor;
double mana_factor;
double endurance_factor;
+82
View File
@@ -0,0 +1,82 @@
#include "global_define.h"
#include "types.h"
#include <string.h>
#include <zlib.h>
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
if (deflateInit(&zstream, Z_FINISH) != Z_OK)
return 0;
return deflateBound(&zstream, len);
}
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
int zerror;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);
zstream.avail_out = out_len_max;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return (uint32)zstream.total_out;
}
else
{
zerror = deflateEnd(&zstream);
return 0;
}
}
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) {
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
zstream.avail_out = out_len_max;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2(&zstream, 15);
if (i != Z_OK) {
return 0;
}
zerror = inflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END) {
inflateEnd(&zstream);
return zstream.total_out;
}
else {
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd(&zstream);
return 0;
}
}
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len);
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max);
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max);
}
+10
View File
@@ -472,6 +472,16 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertCorpseDeblob();
/* Fetch EQEmu Server script */
if (!std::ifstream("eqemu_server.pl")){
std::cout << "Pulling down automatic database upgrade script..." << std::endl;
#ifdef _WIN32
system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\"");
#else
system("wget --no-check-certificate -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl");
#endif
}
/* Run EQEmu Server script (Checks for database updates) */
system("perl eqemu_server.pl ran_from_world");
-65
View File
@@ -18,68 +18,3 @@
*/
#include "emu_constants.h"
const char* EQEmu::bug::CategoryIDToCategoryName(CategoryID category_id) {
switch (category_id) {
case catVideo:
return "Video";
case catAudio:
return "Audio";
case catPathing:
return "Pathing";
case catQuest:
return "Quest";
case catTradeskills:
return "Tradeskills";
case catSpellStacking:
return "Spell stacking";
case catDoorsPortals:
return "Doors/Portals";
case catItems:
return "Items";
case catNPC:
return "NPC";
case catDialogs:
return "Dialogs";
case catLoNTCG:
return "LoN - TCG";
case catMercenaries:
return "Mercenaries";
case catOther:
default:
return "Other";
}
}
EQEmu::bug::CategoryID EQEmu::bug::CategoryNameToCategoryID(const char* category_name) {
if (!category_name)
return catOther;
if (!strcmp(category_name, "Video"))
return catVideo;
if (!strcmp(category_name, "Audio"))
return catAudio;
if (!strcmp(category_name, "Pathing"))
return catPathing;
if (!strcmp(category_name, "Quest"))
return catQuest;
if (!strcmp(category_name, "Tradeskills"))
return catTradeskills;
if (!strcmp(category_name, "Spell stacking"))
return catSpellStacking;
if (!strcmp(category_name, "Doors/Portals"))
return catDoorsPortals;
if (!strcmp(category_name, "Items"))
return catItems;
if (!strcmp(category_name, "NPC"))
return catNPC;
if (!strcmp(category_name, "Dialogs"))
return catDialogs;
if (!strcmp(category_name, "LoN - TCG"))
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}
+1 -36
View File
@@ -24,7 +24,7 @@
#include "emu_legacy.h"
#include "emu_versions.h"
#include <string.h>
#include <string>
namespace EQEmu
@@ -114,11 +114,7 @@ namespace EQEmu
const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2;
const size_t CharacterCreationMax = RoF2::constants::CharacterCreationLimit;
const size_t SayLinkOpenerSize = 1;
const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize;
const size_t SayLinkTextSize = 256; // this may be varied until it breaks something (tested:374) - the others are constant
const size_t SayLinkCloserSize = 1;
const size_t SayLinkMaximumSize = (SayLinkOpenerSize + SayLinkBodySize + SayLinkTextSize + SayLinkCloserSize);
const int LongBuffs = RoF2::constants::LongBuffs;
const int ShortBuffs = RoF2::constants::ShortBuffs;
@@ -130,37 +126,6 @@ namespace EQEmu
} /*constants*/
namespace bug {
enum CategoryID : uint32 {
catOther = 0,
catVideo,
catAudio,
catPathing,
catQuest,
catTradeskills,
catSpellStacking,
catDoorsPortals,
catItems,
catNPC,
catDialogs,
catLoNTCG,
catMercenaries
};
enum OptionalInfoFlag : uint32 {
infoNoOptionalInfo = 0x0,
infoCanDuplicate = 0x1,
infoCrashBug = 0x2,
infoTargetInfo = 0x4,
infoCharacterFlags = 0x8,
infoUnknownValue = 0xFFFFFFF0
};
const char* CategoryIDToCategoryName(CategoryID category_id);
CategoryID CategoryNameToCategoryID(const char* category_name);
} // namespace bug
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,
+2 -2
View File
@@ -78,8 +78,6 @@ namespace EQEmu
SLOT_CURSOR_BAG_END = 340,
SLOT_TRIBUTE_BEGIN = 400,
SLOT_TRIBUTE_END = 404,
SLOT_GUILD_TRIBUTE_BEGIN = 450,
SLOT_GUILD_TRIBUTE_END = 451,
SLOT_BANK_BEGIN = 2000,
SLOT_BANK_END = 2023,
SLOT_BANK_BAGS_BEGIN = 2031,
@@ -175,6 +173,8 @@ namespace EQEmu
// POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
static const size_t POTION_BELT_ITEM_COUNT = 5;
static const size_t TEXT_LINK_BODY_LENGTH = 56;
}
}
-3
View File
@@ -9,7 +9,6 @@ N(OP_AcceptNewTask),
N(OP_AckPacket),
N(OP_Action),
N(OP_Action2),
N(OP_AddNimbusEffect),
N(OP_AdventureData),
N(OP_AdventureDetails),
N(OP_AdventureFinish),
@@ -340,7 +339,6 @@ N(OP_MOTD),
N(OP_MoveCoin),
N(OP_MoveDoor),
N(OP_MoveItem),
N(OP_MoveMultipleItems),
N(OP_MoveLogDisregard),
N(OP_MoveLogRequest),
N(OP_MultiLineMsg),
@@ -393,7 +391,6 @@ N(OP_PVPLeaderBoardReply),
N(OP_PVPLeaderBoardRequest),
N(OP_PVPStats),
N(OP_QueryResponseThing),
N(OP_QueryUCSServerStatus),
N(OP_RaidInvite),
N(OP_RaidJoin),
N(OP_RaidUpdate),
+2 -16
View File
@@ -28,7 +28,7 @@
namespace EQEmu
{
namespace versions {
enum class ClientVersion : uint32 {
enum class ClientVersion {
Unknown = 0,
Client62, // Build: 'Aug 4 2005 15:40:59'
Titanium, // Build: 'Oct 31 2005 10:33:37'
@@ -72,7 +72,7 @@ namespace EQEmu
uint32 ConvertClientVersionToExpansion(ClientVersion client_version);
enum class MobVersion : uint32 {
enum class MobVersion {
Unknown = 0,
Client62,
Titanium,
@@ -121,20 +121,6 @@ namespace EQEmu
ClientVersion ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version);
MobVersion ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version);
enum UCSVersion : char {
ucsUnknown = '\0',
ucsClient62Chat = 'A',
ucsClient62Mail = 'a',
ucsTitaniumChat = 'B',
ucsTitaniumMail = 'b',
ucsSoFCombined = 'C',
ucsSoDCombined = 'D',
ucsUFCombined = 'E',
ucsRoFCombined = 'F',
ucsRoF2Combined = 'G'
};
} /*versions*/
} /*EQEmu*/
+48 -81
View File
@@ -280,7 +280,7 @@ union
// horse: 0=brown, 1=white, 2=black, 3=tan
};
/*0340*/ uint32 spawnId; // Spawn Id
/*0344*/ float bounding_radius; // used in melee, overrides calc
/*0344*/ uint8 unknown0344[3];
/*0347*/ uint8 IsMercenary;
/*0348*/ EQEmu::TintProfile equipment_tint;
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
@@ -551,7 +551,6 @@ struct BlockedBuffs_Struct
/*86*/ uint16 Flags;
};
// same for adding
struct RemoveNimbusEffect_Struct
{
/*00*/ uint32 spawnid; // Spawn ID
@@ -855,7 +854,6 @@ static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size r
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 240;
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;
@@ -995,8 +993,7 @@ struct PlayerProfile_Struct
/*4768*/ int32 platinum_shared; // Platinum shared between characters
/*4772*/ uint8 unknown4808[24];
/*4796*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
/*5196*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL];
/*5296*/ uint8 unknown5132[84];
/*5196*/ uint8 unknown5132[184];
/*5380*/ uint32 pvp2; //
/*5384*/ uint32 unknown5420; //
/*5388*/ uint32 pvptype; //
@@ -1253,22 +1250,21 @@ struct Action_Struct
{
/* 00 */ uint16 target; // id of target
/* 02 */ uint16 source; // id of caster
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/* 10 */ float force;
/* 14 */ float hit_heading;
/* 18 */ float hit_pitch;
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
/* 23 */ uint16 unknown23; // OSX says min_damage
/* 25 */ uint16 unknown25; // OSX says tohit
/* 04 */ uint16 level; // level of caster
/* 06 */ uint16 instrument_mod;
/* 08 */ uint32 bard_focus_id;
/* 12 */ uint16 unknown16;
// some kind of sequence that's the same in both actions
// as well as the combat damage, to tie em together?
/* 14 */ uint32 sequence;
/* 18 */ uint32 unknown18;
/* 22 */ uint8 type; // 231 (0xE7) for spells
/* 23 */ uint32 unknown23;
/* 27 */ uint16 spell; // spell id being cast
/* 29 */ uint8 spell_level;
/* 29 */ uint8 unknown29;
// this field seems to be some sort of success flag, if it's 4
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
// newer clients have some data for setting LaunchSpellData when effect_flag & 4
// /* 31 */ uint8 spell_gem;
// /* 32 */ uint32 inventory_slot;
// /* 36 */ uint32 item_cast_type;
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
/* 31 */
};
// this is what prints the You have been struck. and the regular
@@ -1278,12 +1274,12 @@ struct CombatDamage_Struct
{
/* 00 */ uint16 target;
/* 02 */ uint16 source;
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells, skill
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
/* 05 */ uint16 spellid;
/* 07 */ uint32 damage;
/* 11 */ float force;
/* 15 */ float hit_heading; // see above notes in Action_Struct
/* 19 */ float hit_pitch;
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
};
@@ -3324,32 +3320,23 @@ struct GuildMakeLeader{
char target[64];
};
struct BugReport_Struct {
/*0000*/ uint32 category_id;
/*0004*/ char category_name[64];
/*0068*/ char reporter_name[64];
/*0132*/ char unused_0132[32];
/*0164*/ char ui_path[128];
/*0292*/ float pos_x;
/*0296*/ float pos_y;
/*0300*/ float pos_z;
/*0304*/ uint32 heading;
/*0308*/ uint32 unused_0308;
/*0312*/ uint32 time_played;
/*0316*/ char padding_0316[8];
/*0324*/ uint32 target_id;
/*0328*/ char padding_0328[140];
/*0468*/ uint32 unknown_0468; // seems to always be '0'
/*0472*/ char target_name[64];
/*0536*/ uint32 optional_info_mask;
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0540*/ char unused_0540[2052];
/*2592*/ char bug_report[2050];
/*4642*/ char system_info[4098];
/*8740*/
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ char unknown308[160];
/*0468*/ char target_name[64];
/*0532*/ uint32 type;
/*0536*/ char unknown536[2052];
/*2584*/ char bug[2048];
/*4632*/ char unknown4632[6];
/*4638*/ char system_info[4094];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -3376,21 +3363,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -4778,7 +4764,6 @@ struct BuffIconEntry_Struct
uint32 spell_id;
int32 tics_remaining;
uint32 num_hits;
char caster[64];
};
struct BuffIcon_Struct
@@ -4788,7 +4773,6 @@ struct BuffIcon_Struct
uint16 count;
uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC
int32 tic_timer;
int32 name_lengths; // so ahh we kind of do these packets hacky, this is the total length of all the names to make creating the real packets in the translators easier
BuffIconEntry_Struct entries[0];
};
@@ -5367,23 +5351,6 @@ struct AuraDestory_Struct {
};
// 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
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char Augment6[5];
/*036*/ char IsEvolving[1];
/*037*/ char EvolveGroup[4];
/*041*/ char EvolveLevel[2];
/*043*/ char OrnamentIcon[5];
/*048*/ char Hash[8];
/*056*/
};
// Restore structure packing to default
#pragma pack()
+336 -96
View File
@@ -23,112 +23,351 @@
#include <iostream>
#include <sstream>
std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
std::string EQEmuConfig::ConfigFile = "eqemu_config.xml";
EQEmuConfig *EQEmuConfig::_config = nullptr;
void EQEmuConfig::parse_config() {
ShortName = _root["server"]["world"].get("shortname", "").asString();
LongName = _root["server"]["world"].get("longname", "").asString();
WorldAddress = _root["server"]["world"].get("address", "").asString();
LocalAddress = _root["server"]["world"].get("localaddress", "").asString();
MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str());
SharedKey = _root["server"]["world"].get("key", "").asString();
LoginCount = 0;
if (_root["server"]["world"]["loginserver"].isObject()) {
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
LoginLegacy = false;
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") LoginLegacy = true;
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
void EQEmuConfig::do_world(TiXmlElement *ele)
{
const char *text;
TiXmlElement * sub_ele;;
text = ParseTextBlock(ele, "shortname");
if (text) {
ShortName = text;
}
text = ParseTextBlock(ele, "longname");
if (text) {
LongName = text;
}
text = ParseTextBlock(ele, "address", true);
if (text) {
WorldAddress = text;
}
text = ParseTextBlock(ele, "localaddress", true);
if (text) {
LocalAddress = text;
}
text = ParseTextBlock(ele, "maxclients", true);
if (text) {
MaxClients = atoi(text);
}
// Get the <key> element
text = ParseTextBlock(ele, "key", true);
if (text) {
SharedKey = text;
}
// Get the <loginserver> element
sub_ele = ele->FirstChildElement("loginserver");
if (sub_ele) {
text = ParseTextBlock(sub_ele, "host", true);
if (text) {
LoginHost = text;
}
text = ParseTextBlock(sub_ele, "port", true);
if (text) {
LoginPort = atoi(text);
}
text = ParseTextBlock(sub_ele, "legacy", true);
if (text) {
LoginLegacy = atoi(text) > 0 ? true : false;
}
text = ParseTextBlock(sub_ele, "account", true);
if (text) {
LoginAccount = text;
}
text = ParseTextBlock(sub_ele, "password", true);
if (text) {
LoginPassword = text;
}
} else {
char str[32];
loginlist.Clear();
char str[32];
do {
sprintf(str, "loginserver%i", ++LoginCount);
if (!_root["server"]["world"][str].isObject()) {
break;
sub_ele = ele->FirstChildElement(str);
if (sub_ele) {
auto loginconfig = new LoginConfig;
text = ParseTextBlock(sub_ele, "host", true);
if (text) {
loginconfig->LoginHost = text;
}
text = ParseTextBlock(sub_ele, "port", true);
if (text) {
loginconfig->LoginPort = atoi(text);
}
text = ParseTextBlock(sub_ele, "legacy", true);
if (text) {
loginconfig->LoginLegacy = atoi(text) > 0 ? true : false;
}
text = ParseTextBlock(sub_ele, "account", true);
if (text) {
loginconfig->LoginAccount = text;
}
text = ParseTextBlock(sub_ele, "password", true);
if (text) {
loginconfig->LoginPassword = text;
}
loginlist.Insert(loginconfig);
}
auto loginconfig = new LoginConfig;
loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString();
loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str());
loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString();
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
loginconfig->LoginLegacy = false;
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") loginconfig->LoginLegacy = true;
loginlist.Insert(loginconfig);
} while (LoginCount < 100);
} while (sub_ele);
}
// Check for locked
sub_ele = ele->FirstChildElement("locked");
if (sub_ele != nullptr) {
Locked = true;
}
// Get the <tcp> element
sub_ele = ele->FirstChildElement("tcp");
if (sub_ele != nullptr) {
text = sub_ele->Attribute("ip");
if (text) {
WorldIP = text;
}
text = sub_ele->Attribute("port");
if (text) {
WorldTCPPort = atoi(text);
}
}
//<locked> from xml converts to json as locked: "", so i default to "false".
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true
Locked = false;
if (_root["server"]["world"].get("locked", "false").asString() == "true") Locked = true;
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
TelnetEnabled = false;
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") TelnetEnabled = true;
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
WorldHTTPEnabled = false;
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") WorldHTTPEnabled = true;
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
LuaModuleDir = _root["server"]["directories"].get("lua_modules", "lua_modules/").asString();
PatchDir = _root["server"]["directories"].get("patches", "./").asString();
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString();
LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString();
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str());
#ifdef WIN32
ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString();
#else
ZoneExe = _root["server"]["launcher"].get("exe", "./zone").asString();
#endif
sub_ele = ele->FirstChildElement("telnet");
if (sub_ele != nullptr) {
text = sub_ele->Attribute("ip");
if (text) {
TelnetIP = text;
}
text = sub_ele->Attribute("port");
if (text) {
TelnetTCPPort = atoi(text);
}
text = sub_ele->Attribute("enabled");
if (text && !strcasecmp(text, "true")) {
TelnetEnabled = true;
}
}
// Get the <http> element
sub_ele = ele->FirstChildElement("http");
if (sub_ele != nullptr) {
// text = sub_ele->Attribute("ip");
// if (text)
// WorldIP=text;
text = sub_ele->Attribute("mimefile");
if (text) {
WorldHTTPMimeFile = text;
}
text = sub_ele->Attribute("port");
if (text) {
WorldHTTPPort = atoi(text);
}
text = sub_ele->Attribute("enabled");
if (text && !strcasecmp(text, "true")) {
WorldHTTPEnabled = true;
}
}
}
void EQEmuConfig::do_chatserver(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "host", true);
if (text) {
ChatHost = text;
}
text = ParseTextBlock(ele, "port", true);
if (text) {
ChatPort = atoi(text);
}
}
void EQEmuConfig::do_mailserver(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "host", true);
if (text) {
MailHost = text;
}
text = ParseTextBlock(ele, "port", true);
if (text) {
MailPort = atoi(text);
}
}
void EQEmuConfig::do_database(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "host", true);
if (text) {
DatabaseHost = text;
}
text = ParseTextBlock(ele, "port", true);
if (text) {
DatabasePort = atoi(text);
}
text = ParseTextBlock(ele, "username", true);
if (text) {
DatabaseUsername = text;
}
text = ParseTextBlock(ele, "password", true);
if (text) {
DatabasePassword = text;
}
text = ParseTextBlock(ele, "db", true);
if (text) {
DatabaseDB = text;
}
}
void EQEmuConfig::do_qsdatabase(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "host", true);
if (text) {
QSDatabaseHost = text;
}
text = ParseTextBlock(ele, "port", true);
if (text) {
QSDatabasePort = atoi(text);
}
text = ParseTextBlock(ele, "username", true);
if (text) {
QSDatabaseUsername = text;
}
text = ParseTextBlock(ele, "password", true);
if (text) {
QSDatabasePassword = text;
}
text = ParseTextBlock(ele, "db", true);
if (text) {
QSDatabaseDB = text;
}
}
void EQEmuConfig::do_zones(TiXmlElement *ele)
{
const char *text;
TiXmlElement *sub_ele;
// TiXmlNode *node,*sub_node;
text = ParseTextBlock(ele, "defaultstatus", true);
if (text) {
DefaultStatus = atoi(text);
}
// Get the <ports> element
sub_ele = ele->FirstChildElement("ports");
if (sub_ele != nullptr) {
text = sub_ele->Attribute("low");
if (text) {
ZonePortLow = atoi(text);
};
text = sub_ele->Attribute("high");
if (text) {
ZonePortHigh = atoi(text);
}
}
}
void EQEmuConfig::do_files(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "spells", true);
if (text) {
SpellsFile = text;
}
text = ParseTextBlock(ele, "opcodes", true);
if (text) {
OpCodesFile = text;
}
text = ParseTextBlock(ele, "plugin.pl", true);
if (text) {
PluginPlFile = text;
}
}
void EQEmuConfig::do_directories(TiXmlElement *ele)
{
const char *text;
text = ParseTextBlock(ele, "maps", true);
if (text) {
MapDir = text;
if ( MapDir.back() != '/' )
MapDir += '/';
}
text = ParseTextBlock(ele, "quests", true);
if (text) {
QuestDir = text;
if ( QuestDir.back() != '/' )
QuestDir += '/';
}
text = ParseTextBlock(ele, "plugins", true);
if (text) {
PluginDir = text;
if ( PluginDir.back() != '/' )
PluginDir += '/';
}
text = ParseTextBlock(ele, "lua_modules", true);
if (text) {
LuaModuleDir = text;
if ( LuaModuleDir.back() != '/' )
LuaModuleDir += '/';
}
text = ParseTextBlock(ele, "patches", true);
if (text) {
PatchDir = text;
if ( PatchDir.back() != '/' )
PatchDir += '/';
}
text = ParseTextBlock(ele, "shared_memory", true);
if (text) {
SharedMemDir = text;
if ( SharedMemDir.back() != '/' )
SharedMemDir += '/';
}
//Not Fully Implemented yet LogDir
text = ParseTextBlock(ele, "logs", true);
if (text) {
LogDir = text;
if ( LogDir.back() != '/' )
LogDir += '/';
}
}
void EQEmuConfig::do_launcher(TiXmlElement *ele)
{
const char *text;
TiXmlElement *sub_ele;
text = ParseTextBlock(ele, "logprefix", true);
if (text) {
LogPrefix = text;
}
text = ParseTextBlock(ele, "logsuffix", true);
if (text) {
LogSuffix = text;
}
// Get the <exe> element
text = ParseTextBlock(ele, "exe", true);
if (text) {
ZoneExe = text;
}
// Get the <timers> element
sub_ele = ele->FirstChildElement("timers");
if (sub_ele != nullptr) {
text = sub_ele->Attribute("restart");
if (text) {
RestartWait = atoi(text);
}
text = sub_ele->Attribute("reterminate");
if (text) {
TerminateWait = atoi(text);
}
text = sub_ele->Attribute("initial");
if (text) {
InitialBootWait = atoi(text);
}
text = sub_ele->Attribute("interval");
if (text) {
ZoneBootInterval = atoi(text);
}
}
}
std::string EQEmuConfig::GetByName(const std::string &var_name) const
{
if (var_name == "ShortName") {
@@ -325,3 +564,4 @@ void EQEmuConfig::Dump() const
std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl;
// std::cout << "DynamicCount = " << DynamicCount << std::endl;
}
+84 -31
View File
@@ -18,9 +18,8 @@
#ifndef __EQEmuConfig_H
#define __EQEmuConfig_H
#include "json/json.h"
#include "xml_parser.h"
#include "linked_list.h"
#include <fstream>
struct LoginConfig {
std::string LoginHost;
@@ -30,7 +29,7 @@ struct LoginConfig {
bool LoginLegacy;
};
class EQEmuConfig
class EQEmuConfig : public XMLParser
{
public:
virtual std::string GetByName(const std::string &var_name) const;
@@ -81,10 +80,6 @@ class EQEmuConfig
std::string QSDatabaseDB;
uint16 QSDatabasePort;
// From <nats/>
std::string NATSHost;
uint16 NATSPort;
// From <files/>
std::string SpellsFile;
std::string OpCodesFile;
@@ -120,14 +115,88 @@ class EQEmuConfig
protected:
static EQEmuConfig *_config;
Json::Value _root;
static std::string ConfigFile;
void parse_config();
#define ELEMENT(name) \
void do_##name(TiXmlElement *ele);
#include "eqemu_config_elements.h"
EQEmuConfig()
{
{
// import the needed handler prototypes
#define ELEMENT(name) \
Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name;
#include "eqemu_config_elements.h"
// Set sane defaults
// Login server
LoginHost = "login.eqemulator.net";
LoginPort = 5998;
LoginLegacy = false;
// World
Locked = false;
WorldTCPPort = 9000;
TelnetTCPPort = 9001;
TelnetEnabled = false;
WorldHTTPEnabled = false;
WorldHTTPPort = 9080;
WorldHTTPMimeFile = "mime.types";
SharedKey = ""; //blank disables authentication
// Mail
ChatHost = "eqchat.eqemulator.net";
ChatPort = 7778;
// Mail
MailHost = "eqmail.eqemulator.net";
MailPort = 7779;
// Mysql
DatabaseHost = "localhost";
DatabasePort = 3306;
DatabaseUsername = "eq";
DatabasePassword = "eq";
DatabaseDB = "eq";
// QueryServ Database
QSDatabaseHost = "localhost";
QSDatabasePort = 3306;
QSDatabaseUsername = "eq";
QSDatabasePassword = "eq";
QSDatabaseDB = "eq";
// Files
SpellsFile = "spells_us.txt";
OpCodesFile = "opcodes.conf";
PluginPlFile = "plugin.pl";
// Dirs
MapDir = "Maps/";
QuestDir = "quests/";
PluginDir = "plugins/";
LuaModuleDir = "lua_modules/";
PatchDir = "./";
SharedMemDir = "shared/";
LogDir = "logs/";
// Launcher
LogPrefix = "logs/zone-";
LogSuffix = ".log";
RestartWait = 10000; //milliseconds
TerminateWait = 10000; //milliseconds
InitialBootWait = 20000; //milliseconds
ZoneBootInterval = 2000; //milliseconds
#ifdef WIN32
ZoneExe = "zone.exe";
#else
ZoneExe = "./zone";
#endif
// Zones
ZonePortLow = 7000;
ZonePortHigh = 7999;
DefaultStatus = 0;
// For where zones need to connect to.
WorldIP = "127.0.0.1";
TelnetIP = "127.0.0.1";
// Dynamics to start
//DynamicCount=5;
MaxClients = -1;
LoginCount = 0;
}
virtual ~EQEmuConfig() {}
@@ -136,7 +205,9 @@ class EQEmuConfig
// Produce a const singleton
static const EQEmuConfig *get()
{
LoadConfig();
if (_config == nullptr) {
LoadConfig();
}
return (_config);
}
@@ -150,28 +221,10 @@ class EQEmuConfig
static bool LoadConfig()
{
if (_config != nullptr) {
return true;
delete _config;
}
_config = new EQEmuConfig;
return parseFile();
}
// Load config file and parse data
static bool parseFile() {
if (_config == nullptr) {
return LoadConfig();
}
std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary);
try {
fconfig >> _config->_root;
_config->parse_config();
}
catch (std::exception) {
return false;
}
return true;
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(), "server");
}
void Dump() const;
-2
View File
@@ -104,7 +104,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::MySQLError].log_to_console = Logs::General;
log_settings[Logs::Login_Server].log_to_console = Logs::General;
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
log_settings[Logs::NATS].log_to_console = Logs::General;
/* Set Category enabled status on defaults */
log_settings[Logs::World_Server].is_category_enabled = 1;
@@ -114,7 +113,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Crash].is_category_enabled = 1;
log_settings[Logs::MySQLError].is_category_enabled = 1;
log_settings[Logs::Login_Server].is_category_enabled = 1;
log_settings[Logs::NATS].is_category_enabled = 1;
/* Declare process file names for log writing
If there is no process_file_name declared, no log file will be written, simply
+1 -7
View File
@@ -88,9 +88,6 @@ enum LogCategory {
Headless_Client,
HP_Update,
FixZ,
Food,
Traps,
NATS,
MaxCategoryID /* Don't Remove this*/
};
@@ -143,10 +140,7 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
"Client Login",
"Headless Client",
"HP Update",
"FixZ",
"Food",
"Traps",
"NATS"
"FixZ"
};
}
+7 -4
View File
@@ -1,32 +1,35 @@
#pragma once
#include <functional>
#include "../any.h"
#include "event_loop.h"
namespace EQ {
class BackgroundTask
{
public:
typedef std::function<void(void)> BackgroundTaskFunction;
typedef std::function<void(EQEmu::Any&)> BackgroundTaskFunction;
struct BackgroundTaskBaton
{
BackgroundTaskFunction fn;
BackgroundTaskFunction on_finish;
EQEmu::Any data;
};
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish) {
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish, EQEmu::Any data) {
uv_work_t *m_work = new uv_work_t;
memset(m_work, 0, sizeof(uv_work_t));
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
baton->fn = fn;
baton->on_finish = on_finish;
baton->data = data;
m_work->data = baton;
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->fn();
baton->fn(baton->data);
}, [](uv_work_t* req, int status) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->on_finish();
baton->on_finish(baton->data);
delete baton;
delete req;
});
-8
View File
@@ -219,9 +219,6 @@ enum { //some random constants
//the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
#define USE_NPC_RANGE2 200*200 //arbitrary right now
// Squared range for rampage 75.0 * 75.0 for now
#define NPC_RAMPAGE_RANGE2 5625.0f
//the formula for experience for killing a mob.
//level is the only valid variable to use
#define EXP_FORMULA level*level*75*35/10
@@ -279,11 +276,6 @@ enum {
#define SAYLINK_ITEM_ID 0xFFFFF
// consumption timers for food/drink here instead of rules because the client
// uses these. Times in ms.
#define CONSUMPTION_TIMER 46000
#define CONSUMPTION_MNK_TIMER 92000
/*
Developer configuration
+1 -4
View File
@@ -111,8 +111,7 @@
#define GLM_COMPILER_GCC70 0x02000A00
#define GLM_COMPILER_GCC71 0x02000B00
#define GLM_COMPILER_GCC72 0x02000C00
#define GLM_COMPILER_GCC73 0x02000D00
#define GLM_COMPILER_GCC80 0x02000E00
#define GLM_COMPILER_GCC80 0x02000D00
// CUDA
#define GLM_COMPILER_CUDA 0x10000000
@@ -284,8 +283,6 @@
# define GLM_COMPILER (GLM_COMPILER_GCC71)
# elif (__GNUC__ == 7) && (__GNUC_MINOR__ == 2)
# define GLM_COMPILER (GLM_COMPILER_GCC72)
# elif (__GNUC__ == 7) && (__GNUC_MINOR__ == 3)
# define GLM_COMPILER (GLM_COMPILER_GCC73)
# elif (__GNUC__ >= 8)
# define GLM_COMPILER (GLM_COMPILER_GCC80)
# else
-1254
View File
File diff suppressed because it is too large Load Diff
+14 -52
View File
@@ -194,70 +194,32 @@ uint32 rnd_hash( time_t t, clock_t c )
float EQ13toFloat(int d)
{
return static_cast<float>(d) / 64.0f;
return ( float(d)/float(1<<2));
}
float NewEQ13toFloat(int d)
{
return ( float(d)/float(1<<6));
}
float EQ19toFloat(int d)
{
return static_cast<float>(d) / 8.0f;
return ( float(d)/float(1<<3));
}
int FloatToEQ13(float d)
{
return static_cast<int>(d * 64.0f);
return int(d*float(1<<2));
}
int NewFloatToEQ13(float d)
{
return int(d*float(1<<6));
}
int FloatToEQ19(float d)
{
return static_cast<int>(d * 8.0f);
}
float EQ12toFloat(int d)
{
return static_cast<float>(d) / 4.0f;
}
int FloatToEQ12(float d)
{
return static_cast<int>((d + 2048.0f) * 4.0f) % 2048;
}
float EQ10toFloat(int d)
{
return static_cast<float>(d) / 20.0f;
}
int FloatToEQ10(float d)
{
return static_cast<int>(d * 20.0f);
}
float EQSpeedRunToFloat(int d)
{
return static_cast<float>(d) / 40.0f;
}
int FloatToEQSpeedRun(float d)
{
return static_cast<int>(d * 40.0f);
}
float FixHeading(float in)
{
int i = 0;
if (in >= 512.0f) {
do {
in -= 512.0f;
} while (in >= 512.0f && i++ <= 5);
}
i = 0;
if (in < 0.0f) {
do {
in += 512.0f;
} while (in < 0.0f && i++ <= 5);
}
return in;
return int(d*float(1<<3));
}
/*
+2 -14
View File
@@ -50,25 +50,13 @@ uint32 ResolveIP(const char* hostname, char* errbuf = 0);
bool ParseAddress(const char* iAddress, uint32* oIP, uint16* oPort, char* errbuf = 0);
void CoutTimestamp(bool ms = true);
float EQ13toFloat(int d);
float NewEQ13toFloat(int d);
float EQ19toFloat(int d);
float EQHtoFloat(int d);
int FloatToEQ13(float d);
int NewFloatToEQ13(float d);
int FloatToEQ19(float d);
int FloatToEQH(float d);
float EQ12toFloat(int d);
int FloatToEQ12(float d);
float EQ10toFloat(int d);
int FloatToEQ10(float d);
// this is also a 10 bit float
float EQSpeedRunToFloat(int d);
int FloatToEQSpeedRun(float d);
// brings heading back into EQ angles range
float FixHeading(float in);
uint32 SwapBits21and22(uint32 mask);
uint32 Catch22(uint32 mask);
+2 -2
View File
@@ -165,7 +165,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend()
{
auto iter = m_connections.begin();
while (iter != m_connections.end()) {
auto &connection = iter->second;
auto connection = iter->second;
auto status = connection->m_status;
switch (status)
@@ -1397,4 +1397,4 @@ EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t exp
}
return SequencePast;
}
}
+56 -60
View File
@@ -57,11 +57,11 @@ namespace RoF
static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rofSlot);
static inline uint32 RoFToServerCorpseSlot(uint32 rofCorpseSlot);
// server to client say link converter
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void RoFToServerSayLink(std::string& serverSayLink, const std::string& rofSayLink);
// client to server text link converter
static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink);
static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot);
@@ -163,23 +163,22 @@ namespace RoF
OUT(level);
eq->unknown06 = 0;
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
eq->bard_focus_id = emu->bard_focus_id;
eq->knockback_angle = emu->sequence;
eq->unknown22 = 0;
OUT(type);
eq->damage = 0;
eq->unknown31 = 0;
OUT(spell);
OUT(spell_level);
OUT(effect_flag);
eq->spell_gem = 0;
eq->slot.Type = INVALID_INDEX;
eq->slot.Unknown02 = 0;
eq->slot.Slot = INVALID_INDEX;
eq->slot.SubIndex = INVALID_INDEX;
eq->slot.AugIndex = INVALID_INDEX;
eq->slot.Unknown01 = 0;
eq->item_cast_type = 0;
eq->level2 = eq->level;
eq->effect_flag = emu->buff_unknown;
eq->unknown39 = 14;
eq->unknown43 = 0;
eq->unknown44 = 17;
eq->unknown45 = 0;
eq->unknown46 = -1;
eq->unknown50 = 0;
eq->unknown54 = 0;
FINISH_ENCODE();
}
@@ -461,7 +460,7 @@ namespace RoF
{
SETUP_VAR_ENCODE(BuffIcon_Struct);
uint32 sz = 12 + (17 * emu->count) + emu->name_lengths; // 17 includes nullterm
uint32 sz = 12 + (17 * emu->count);
__packet->size = sz;
__packet->pBuffer = new unsigned char[sz];
memset(__packet->pBuffer, 0, sz);
@@ -477,7 +476,7 @@ namespace RoF
__packet->WriteUInt32(emu->entries[i].spell_id);
__packet->WriteUInt32(emu->entries[i].tics_remaining);
__packet->WriteUInt32(emu->entries[i].num_hits); // Unknown
__packet->WriteString(emu->entries[i].caster);
__packet->WriteString("");
}
__packet->WriteUInt8(emu->type); // Unknown
@@ -521,7 +520,7 @@ namespace RoF
std::string old_message = emu->message;
std::string new_message;
ServerToRoFSayLink(new_message, old_message);
ServerToRoFTextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@@ -660,8 +659,8 @@ namespace RoF
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
@@ -848,7 +847,7 @@ namespace RoF
std::string old_message = emu->message;
std::string new_message;
ServerToRoFSayLink(new_message, old_message);
ServerToRoFTextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -900,7 +899,7 @@ namespace RoF
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToRoFSayLink(new_message_array[i], old_message_array[i]);
ServerToRoFTextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -2185,11 +2184,11 @@ namespace RoF
outapp->WriteUInt32(emu->skills[r]);
}
outapp->WriteUInt32(structs::MAX_PP_INNATE_SKILL); // Innate Skills count
outapp->WriteUInt32(25); // Unknown count
for (uint32 r = 0; r < structs::MAX_PP_INNATE_SKILL; r++)
for (uint32 r = 0; r < 25; r++)
{
outapp->WriteUInt32(emu->InnateSkills[r]); // Innate Skills (regen, slam, etc)
outapp->WriteUInt32(0); // Unknown
}
outapp->WriteUInt32(structs::MAX_PP_DISCIPLINES); // Discipline count
@@ -3296,7 +3295,7 @@ namespace RoF
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToRoFSayLink(new_message, old_message);
ServerToRoFTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -3370,7 +3369,7 @@ namespace RoF
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToRoFSayLink(new_message, old_message);
ServerToRoFTextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
@@ -3848,12 +3847,9 @@ namespace RoF
OUT(y);
OUT(x);
OUT(z)
OUT(zone_reason);
OUT(zone_reason);
OUT(success);
if (eq->success < 0)
eq->success -= 1;
FINISH_ENCODE();
}
@@ -4356,7 +4352,7 @@ namespace RoF
std::string old_message = InBuffer;
std::string new_message;
RoFToServerSayLink(new_message, old_message);
RoFToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -4467,7 +4463,7 @@ namespace RoF
IN(type);
IN(spellid);
IN(damage);
IN(hit_heading);
IN(meleepush_xy);
FINISH_DIRECT_DECODE();
}
@@ -4490,7 +4486,7 @@ namespace RoF
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
RoFToServerSayLink(new_message, old_message);
RoFToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -5917,19 +5913,19 @@ namespace RoF
return (rofCorpseSlot - 1);
}
static inline void ServerToRoFSayLink(std::string& rofSayLink, const std::string& serverSayLink)
static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
rofSayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
rofTextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
rofSayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
rofTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -5939,36 +5935,36 @@ namespace RoF
// RoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (55)
// Diff: ^
rofSayLink.push_back('\x12');
rofSayLink.append(segments[segment_iter].substr(0, 41));
rofTextLink.push_back('\x12');
rofTextLink.append(segments[segment_iter].substr(0, 41));
if (segments[segment_iter][41] == '0')
rofSayLink.push_back(segments[segment_iter][42]);
rofTextLink.push_back(segments[segment_iter][42]);
else
rofSayLink.push_back('F');
rofTextLink.push_back('F');
rofSayLink.append(segments[segment_iter].substr(43));
rofSayLink.push_back('\x12');
rofTextLink.append(segments[segment_iter].substr(43));
rofTextLink.push_back('\x12');
}
else {
rofSayLink.append(segments[segment_iter]);
rofTextLink.append(segments[segment_iter]);
}
}
}
static inline void RoFToServerSayLink(std::string& serverSayLink, const std::string& rofSayLink)
static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (rofSayLink.find('\x12') == std::string::npos)) {
serverSayLink = rofSayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rofTextLink.find('\x12') == std::string::npos)) {
serverTextLink = rofTextLink;
return;
}
auto segments = SplitString(rofSayLink, '\x12');
auto segments = SplitString(rofTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -5978,14 +5974,14 @@ namespace RoF
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter].substr(0, 41));
serverSayLink.push_back('0');
serverSayLink.append(segments[segment_iter].substr(41));
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter].substr(0, 41));
serverTextLink.push_back('0');
serverTextLink.append(segments[segment_iter].substr(41));
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
+51 -55
View File
@@ -57,11 +57,11 @@ namespace RoF2
static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2Slot);
static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot);
// server to client say link converter
static inline void ServerToRoF2SayLink(std::string& rof2SayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void RoF2ToServerSayLink(std::string& serverSayLink, const std::string& rof2SayLink);
// client to server text link converter
static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink);
static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot);
@@ -232,23 +232,22 @@ namespace RoF2
OUT(level);
eq->unknown06 = 0;
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
eq->bard_focus_id = emu->bard_focus_id;
eq->knockback_angle = emu->sequence;
eq->unknown22 = 0;
OUT(type);
eq->damage = 0;
eq->unknown31 = 0;
OUT(spell);
OUT(spell_level);
OUT(effect_flag);
eq->spell_gem = 0;
eq->slot.Type = INVALID_INDEX;
eq->slot.Unknown02 = 0;
eq->slot.Slot = INVALID_INDEX;
eq->slot.SubIndex = INVALID_INDEX;
eq->slot.AugIndex = INVALID_INDEX;
eq->slot.Unknown01 = 0;
eq->item_cast_type = 0;
eq->level2 = eq->level;
eq->effect_flag = emu->buff_unknown;
eq->unknown39 = 14;
eq->unknown43 = 0;
eq->unknown44 = 17;
eq->unknown45 = 0;
eq->unknown46 = -1;
eq->unknown50 = 0;
eq->unknown54 = 0;
FINISH_ENCODE();
}
@@ -529,7 +528,7 @@ namespace RoF2
{
SETUP_VAR_ENCODE(BuffIcon_Struct);
uint32 sz = 12 + (17 * emu->count) + emu->name_lengths; // 17 includes nullterm
uint32 sz = 12 + (17 * emu->count);
__packet->size = sz;
__packet->pBuffer = new unsigned char[sz];
memset(__packet->pBuffer, 0, sz);
@@ -545,7 +544,7 @@ namespace RoF2
__packet->WriteUInt32(emu->entries[i].spell_id);
__packet->WriteUInt32(emu->entries[i].tics_remaining);
__packet->WriteUInt32(emu->entries[i].num_hits); // Unknown
__packet->WriteString(emu->entries[i].caster);
__packet->WriteString("");
}
__packet->WriteUInt8(emu->type); // Unknown
@@ -589,7 +588,7 @@ namespace RoF2
std::string old_message = emu->message;
std::string new_message;
ServerToRoF2SayLink(new_message, old_message);
ServerToRoF2TextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@@ -728,8 +727,8 @@ namespace RoF2
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
@@ -916,7 +915,7 @@ namespace RoF2
std::string old_message = emu->message;
std::string new_message;
ServerToRoF2SayLink(new_message, old_message);
ServerToRoF2TextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -968,7 +967,7 @@ namespace RoF2
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToRoF2SayLink(new_message_array[i], old_message_array[i]);
ServerToRoF2TextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -2262,11 +2261,11 @@ namespace RoF2
outapp->WriteUInt32(emu->skills[r]);
}
outapp->WriteUInt32(structs::MAX_PP_INNATE_SKILL); // Innate Skills count
outapp->WriteUInt32(25); // Unknown count
for (uint32 r = 0; r < structs::MAX_PP_INNATE_SKILL; r++)
for (uint32 r = 0; r < 25; r++)
{
outapp->WriteUInt32(emu->InnateSkills[r]); // Innate Skills (regen, slam, etc)
outapp->WriteUInt32(0); // Unknown
}
outapp->WriteUInt32(structs::MAX_PP_DISCIPLINES); // Discipline count
@@ -3365,7 +3364,7 @@ namespace RoF2
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToRoF2SayLink(new_message, old_message);
ServerToRoF2TextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -3439,7 +3438,7 @@ namespace RoF2
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToRoF2SayLink(new_message, old_message);
ServerToRoF2TextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
@@ -3992,12 +3991,9 @@ namespace RoF2
OUT(y);
OUT(x);
OUT(z)
OUT(zone_reason);
OUT(zone_reason);
OUT(success);
if (eq->success < 0)
eq->success -= 1;
FINISH_ENCODE();
}
@@ -4596,7 +4592,7 @@ namespace RoF2
std::string old_message = InBuffer;
std::string new_message;
RoF2ToServerSayLink(new_message, old_message);
RoF2ToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -4707,7 +4703,7 @@ namespace RoF2
IN(type);
IN(spellid);
IN(damage);
IN(hit_heading);
IN(meleepush_xy);
FINISH_DIRECT_DECODE();
}
@@ -4730,7 +4726,7 @@ namespace RoF2
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
RoF2ToServerSayLink(new_message, old_message);
RoF2ToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -6234,19 +6230,19 @@ namespace RoF2
return (rof2CorpseSlot + EQEmu::legacy::CORPSE_BEGIN - 1);
}
static inline void ServerToRoF2SayLink(std::string& rof2SayLink, const std::string& serverSayLink)
static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
rof2SayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
rof2TextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
rof2SayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
rof2TextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -6256,29 +6252,29 @@ namespace RoF2
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff:
rof2SayLink.push_back('\x12');
rof2SayLink.append(segments[segment_iter]);
rof2SayLink.push_back('\x12');
rof2TextLink.push_back('\x12');
rof2TextLink.append(segments[segment_iter]);
rof2TextLink.push_back('\x12');
}
else {
rof2SayLink.append(segments[segment_iter]);
rof2TextLink.append(segments[segment_iter]);
}
}
}
static inline void RoF2ToServerSayLink(std::string& serverSayLink, const std::string& rof2SayLink)
static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (rof2SayLink.find('\x12') == std::string::npos)) {
serverSayLink = rof2SayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rof2TextLink.find('\x12') == std::string::npos)) {
serverTextLink = rof2TextLink;
return;
}
auto segments = SplitString(rof2SayLink, '\x12');
auto segments = SplitString(rof2TextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -6288,12 +6284,12 @@ namespace RoF2
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff:
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter]);
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter]);
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
+1 -1
View File
@@ -164,7 +164,7 @@ namespace RoF2
ItemPacket11 = 111,
ItemPacket12 = 112,
ItemPacketRecovery = 113,
ItemPacket14 = 115 // Parcel? adds to merchant window too
ItemPacket14 = 115
};
} /*item*/
+62 -76
View File
@@ -131,7 +131,6 @@ static const uint32 MAX_PP_LANGUAGE = 32; // was 25
static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 300;
static const uint32 MAX_PP_DISCIPLINES = 300; // was 200
static const uint32 MAX_GROUP_MEMBERS = 6;
@@ -400,7 +399,7 @@ struct Spawn_Struct_Position
struct Spawn_Struct_Position
{
signed angle:12; // pitch of camera?
signed padding0000:12;
signed y:19;
signed padding0001:1;
@@ -416,7 +415,7 @@ struct Spawn_Struct_Position
signed z:19;
signed padding0020:3;
signed animation:10; // SpeedRun
signed animation:10; // animation
signed deltaY:13;
signed padding0023:9;
};
@@ -430,7 +429,7 @@ struct Spawn_Struct
/*0000*/ //uint8 nullterm1; // hack to null terminate name
/*0064*/ uint32 spawnId;
/*0068*/ uint8 level;
/*0069*/ float bounding_radius; // used in melee, overrides calc
/*0069*/ float unknown1;
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
Spawn_Struct_Bitfields Bitfields;
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
@@ -1156,8 +1155,8 @@ union
/*01012*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [300] 3600 bytes - AAs 12 bytes each
/*04612*/ uint32 skill_count; // Seen 100
/*04616*/ uint32 skills[MAX_PP_SKILL]; // [100] 400 bytes - List of skills
/*05016*/ uint32 InnateSkills_count; // Seen 25
/*05020*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL]; // Most are 255 or 0
/*05016*/ uint32 unknown15_count; // Seen 25
/*05020*/ uint32 unknown_rof15[25]; // Most are 255 or 0
/*05120*/ uint32 discipline_count; // Seen 200
/*05124*/ Disciplines_Struct disciplines; // [200] 800 bytes Known disciplines
/*05924*/ uint32 timestamp_count; // Seen 20
@@ -1462,17 +1461,17 @@ struct Action_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*14*/ uint32 bard_focus_id; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint32 spell; // spell id being cast
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*39*/
};
@@ -1484,21 +1483,25 @@ struct ActionAlt_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*14*/ uint32 bard_focus_id; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint32 spell; // spell id being cast
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*39*/ uint8 spell_gem;
/*40*/ InventorySlot_Struct slot;
/*52*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17
/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0
/*46*/ int32 unknown46; // New field to Underfoot - Seen -1
/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0
/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0
/*56*/
};
@@ -1513,9 +1516,9 @@ struct CombatDamage_Struct
/* 05 */ uint32 spellid;
/* 09 */ int32 damage;
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float hit_heading; // see above notes in Action_Struct
/* 21 */ float hit_pitch;
/* 25 */ uint8 secondary; // 0 for primary hand, 1 for secondary
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 30 */
};
@@ -1823,20 +1826,6 @@ struct MoveItem_Struct
/*0028*/
};
struct MultiMoveItemSub_Struct
{
/*0000*/ InventorySlot_Struct from_slot;
/*0012*/ InventorySlot_Struct to_slot;
/*0024*/ uint32 number_in_stack;
/*0028*/ uint8 unknown[8];
};
struct MultiMoveItem_Struct
{
/*0000*/ uint32 count;
/*0004*/ MultiMoveItemSub_Struct moves[0];
};
//
// from_slot/to_slot
// -1 - destroy
@@ -3601,6 +3590,21 @@ struct GuildSetRank_Struct
/*80*/
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -3627,21 +3631,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -5085,23 +5088,6 @@ struct CrystalCountUpdate_Struct
/*012*/ uint32 CareerEbonCrystals;
};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char Augment6[5];
/*036*/ char IsEvolving[1];
/*037*/ char EvolveGroup[4];
/*041*/ char EvolveLevel[2];
/*043*/ char OrnamentIcon[5];
/*048*/ char Hash[8];
/*056*/
};
}; /*structs*/
}; /*RoF2*/
+60 -60
View File
@@ -131,7 +131,6 @@ static const uint32 MAX_PP_LANGUAGE = 32; // was 25
static const uint32 MAX_PP_SPELLBOOK = 720; // was 480
static const uint32 MAX_PP_MEMSPELL = 16; // was 12
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 300;
static const uint32 MAX_PP_DISCIPLINES = 200; // was 100
static const uint32 MAX_GROUP_MEMBERS = 6;
@@ -408,7 +407,7 @@ struct Spawn_Struct
/*0000*/ //uint8 nullterm1; // hack to null terminate name
/*0064*/ uint32 spawnId;
/*0068*/ uint8 level;
/*0069*/ float bounding_radius; // used in melee, overrides calc
/*0069*/ float unknown1;
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
Spawn_Struct_Bitfields Bitfields;
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
@@ -1097,8 +1096,8 @@ union
/*01012*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [300] 3600 bytes - AAs 12 bytes each
/*04612*/ uint32 skill_count; // Seen 100
/*04616*/ uint32 skills[MAX_PP_SKILL]; // [100] 400 bytes - List of skills
/*05016*/ uint32 InnateSkills_count; // Seen 25
/*05020*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL]; // Most are 255 or 0
/*05016*/ uint32 unknown15_count; // Seen 25
/*05020*/ uint32 unknown_rof15[25]; // Most are 255 or 0
/*05120*/ uint32 discipline_count; // Seen 200
/*05124*/ Disciplines_Struct disciplines; // [200] 800 bytes Known disciplines
/*05924*/ uint32 timestamp_count; // Seen 20
@@ -1450,17 +1449,17 @@ struct Action_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*14*/ uint32 bard_focus_id; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint32 spell; // spell id being cast
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*39*/
};
@@ -1472,21 +1471,25 @@ struct ActionAlt_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*14*/ uint32 bard_focus_id; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint32 spell; // spell id being cast
/*37*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*37*/ uint8 level2; // level of caster again? Or maybe the castee
/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*39*/ uint8 spell_gem;
/*40*/ InventorySlot_Struct slot;
/*52*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17
/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0
/*46*/ int32 unknown46; // New field to Underfoot - Seen -1
/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0
/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0
/*56*/
};
@@ -1501,9 +1504,9 @@ struct CombatDamage_Struct
/* 05 */ uint32 spellid;
/* 09 */ int32 damage;
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float hit_heading; // see above notes in Action_Struct
/* 21 */ float hit_pitch;
/* 25 */ uint8 secondary; // 0 for primary hand, 1 for secondary
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 30 */
};
@@ -3541,6 +3544,21 @@ struct GuildSetRank_Struct
/*80*/
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -3567,21 +3585,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -5002,23 +5019,6 @@ struct MercenaryMerchantRequest_Struct {
struct MercenaryMerchantResponse_Struct {
/*0000*/ uint32 ResponseType;
/*0004*/
};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char Augment6[5];
/*036*/ char IsEvolving[1];
/*037*/ char EvolveGroup[4];
/*041*/ char EvolveLevel[1];
/*042*/ char OrnamentIcon[5];
/*047*/ char Hash[8];
/*055*/
};
}; /*structs*/
+65 -46
View File
@@ -53,11 +53,11 @@ namespace SoD
static inline uint32 SoDToServerSlot(uint32 sodSlot);
static inline uint32 SoDToServerCorpseSlot(uint32 sodCorpseSlot);
// server to client say link converter
static inline void ServerToSoDSayLink(std::string& sodSayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void SoDToServerSayLink(std::string& serverSayLink, const std::string& sodSayLink);
// client to server text link converter
static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink);
static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot);
@@ -161,14 +161,15 @@ namespace SoD
OUT(source);
OUT(level);
OUT(instrument_mod);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
eq->sequence = emu->sequence;
OUT(type);
//OUT(damage);
OUT(spell);
OUT(spell_level);
OUT(effect_flag); // if this is 4, a buff icon is made
eq->level2 = emu->level;
OUT(buff_unknown); // if this is 4, a buff icon is made
//eq->unknown0036 = -1;
//eq->unknown0040 = -1;
//eq->unknown0044 = -1;
FINISH_ENCODE();
}
@@ -345,7 +346,7 @@ namespace SoD
std::string old_message = emu->message;
std::string new_message;
ServerToSoDSayLink(new_message, old_message);
ServerToSoDTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -457,8 +458,8 @@ namespace SoD
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
@@ -624,7 +625,7 @@ namespace SoD
std::string old_message = emu->message;
std::string new_message;
ServerToSoDSayLink(new_message, old_message);
ServerToSoDTextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -676,7 +677,7 @@ namespace SoD
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToSoDSayLink(new_message_array[i], old_message_array[i]);
ServerToSoDTextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -1604,7 +1605,6 @@ namespace SoD
OUT(copper_cursor);
OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword)
OUT_array(InnateSkills, structs::MAX_PP_INNATE_SKILL); // 1:1 direct copy (25 dword)
// OUT(unknown04760[236]);
OUT(toxicity);
@@ -2155,7 +2155,7 @@ namespace SoD
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToSoDSayLink(new_message, old_message);
ServerToSoDTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -2251,7 +2251,7 @@ namespace SoD
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToSoDSayLink(new_message, old_message);
ServerToSoDTextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
@@ -2932,6 +2932,25 @@ namespace SoD
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugStruct);
SETUP_DIRECT_DECODE(BugStruct, structs::BugStruct);
strn0cpy(emu->chartype, eq->chartype, sizeof(emu->chartype));
strn0cpy(emu->name, eq->name, sizeof(emu->name));
strn0cpy(emu->ui, eq->ui, sizeof(emu->ui));
IN(x);
IN(y);
IN(z);
IN(heading);
strn0cpy(emu->target_name, eq->target_name, sizeof(emu->target_name));
strn0cpy(emu->bug, eq->bug, sizeof(emu->bug));
strn0cpy(emu->system_info, eq->system_info, sizeof(emu->system_info));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
@@ -2952,7 +2971,7 @@ namespace SoD
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message;
SoDToServerSayLink(new_message, old_message);
SoDToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size];
@@ -3066,7 +3085,7 @@ namespace SoD
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
SoDToServerSayLink(new_message, old_message);
SoDToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -3916,19 +3935,19 @@ namespace SoD
return (sodCorpseSlot - 1);
}
static inline void ServerToSoDSayLink(std::string& sodSayLink, const std::string& serverSayLink)
static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
sodSayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
sodTextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
sodSayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
sodTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -3938,37 +3957,37 @@ namespace SoD
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
sodSayLink.push_back('\x12');
sodSayLink.append(segments[segment_iter].substr(0, 31));
sodSayLink.append(segments[segment_iter].substr(36, 5));
sodTextLink.push_back('\x12');
sodTextLink.append(segments[segment_iter].substr(0, 31));
sodTextLink.append(segments[segment_iter].substr(36, 5));
if (segments[segment_iter][41] == '0')
sodSayLink.push_back(segments[segment_iter][42]);
sodTextLink.push_back(segments[segment_iter][42]);
else
sodSayLink.push_back('F');
sodTextLink.push_back('F');
sodSayLink.append(segments[segment_iter].substr(43));
sodSayLink.push_back('\x12');
sodTextLink.append(segments[segment_iter].substr(43));
sodTextLink.push_back('\x12');
}
else {
sodSayLink.append(segments[segment_iter]);
sodTextLink.append(segments[segment_iter]);
}
}
}
static inline void SoDToServerSayLink(std::string& serverSayLink, const std::string& sodSayLink)
static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (sodSayLink.find('\x12') == std::string::npos)) {
serverSayLink = sodSayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sodTextLink.find('\x12') == std::string::npos)) {
serverTextLink = sodTextLink;
return;
}
auto segments = SplitString(sodSayLink, '\x12');
auto segments = SplitString(sodTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -3978,16 +3997,16 @@ namespace SoD
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter].substr(0, 31));
serverSayLink.append("00000");
serverSayLink.append(segments[segment_iter].substr(31, 5));
serverSayLink.push_back('0');
serverSayLink.append(segments[segment_iter].substr(36));
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter].substr(0, 31));
serverTextLink.append("00000");
serverTextLink.append(segments[segment_iter].substr(31, 5));
serverTextLink.push_back('0');
serverTextLink.append(segments[segment_iter].substr(36));
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
+1
View File
@@ -104,6 +104,7 @@ D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
+69 -65
View File
@@ -292,7 +292,7 @@ struct Spawn_Struct
/*0000*/ //uint8 nullterm1; // hack to null terminate name
/*0064*/ uint32 spawnId;
/*0068*/ uint8 level;
/*0069*/ float bounding_radius; // used in melee, overrides calc
/*0069*/ float unknown1;
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
Spawn_Struct_Bitfields Bitfields;
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
@@ -818,7 +818,6 @@ static const uint32 MAX_PP_LANGUAGE = 25; //
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;
@@ -924,8 +923,7 @@ struct PlayerProfile_Struct
/*06488*/ uint32 silver_cursor; // Silver Pieces on cursor
/*06492*/ uint32 copper_cursor; // Copper Pieces on cursor
/*06496*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
/*06896*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL];
/*06996*/ uint8 unknown04760[36];
/*06896*/ uint8 unknown04760[136];
/*07032*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*07036*/ uint32 thirst_level; // Drink (ticks till next drink)
/*07040*/ uint32 hunger_level; // Food (ticks till next eat)
@@ -1215,18 +1213,20 @@ struct Action_Struct
{
/* 00 */ uint16 target; // id of target
/* 02 */ uint16 source; // id of caster
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/* 10 */ float force;
/* 14 */ float hit_heading;
/* 18 */ float hit_pitch;
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
/* 23 */ uint16 unknown23; // OSX says min_damage
/* 25 */ uint16 unknown25; // OSX says tohit
/* 04 */ uint16 level; // level of caster
/* 06 */ uint16 instrument_mod; // seems to be fixed to 0x0A
/* 08 */ uint32 unknown08;
/* 12 */ uint16 unknown16;
// some kind of sequence that's the same in both actions
// as well as the combat damage, to tie em together?
/* 14 */ float sequence; // was uint32
/* 18 */ uint32 unknown18;
/* 22 */ uint8 type; // 231 (0xE7) for spells
/* 23 */ uint32 unknown23;
/* 27 */ uint16 spell; // spell id being cast
/* 29 */ uint8 spell_level; // level of caster again? Or maybe the castee
/* 29 */ uint8 level2; // level of caster again? Or maybe the castee
// this field seems to be some sort of success flag, if it's 4
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
/* 31 */
};
@@ -1235,23 +1235,26 @@ struct Action_Struct
// has to do with buff blocking??
struct ActionAlt_Struct // ActionAlt_Struct - Size: 56 bytes
{
/*0000*/ uint16 target; // id of target
/*0002*/ uint16 source; // id of caster
/*0004*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*0006*/ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/*0010*/ float force;
/*0014*/ float hit_heading;
/*0018*/ float hit_pitch;
/*0022*/ uint8 type; // 231 (0xE7) for spells, skill
/*0023*/ uint16 unknown23; // OSX says min_damage
/*0025*/ uint16 unknown25; // OSX says tohit
/*0027*/ uint16 spell; // spell id being cast
/*0029*/ uint8 spell_level; // level of caster again? Or maybe the castee
// this field seems to be some sort of success flag, if it's 4
/*0030*/ uint8 effect_flag; // if this is 4, a buff icon is made
/*0031*/ uint8 spell_slot;
/*0032*/ uint32 slot[5];
/*0052*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
/*0000*/ uint16 target; // Target ID
/*0002*/ uint16 source; // SourceID
/*0004*/ uint16 level; // level of caster
/*0006*/ uint16 instrument_mod; // seems to be fixed to 0x0A
/*0008*/ uint32 unknown08;
/*0012*/ uint16 unknown16;
/*0014*/ uint32 sequence;
/*0018*/ uint32 unknown18;
/*0022*/ uint8 type; // Casts, Falls, Bashes, etc...
/*0023*/ uint32 damage; // Amount of Damage
/*0027*/ uint16 spell; // SpellID
/*0029*/ uint8 unknown29;
/*0030*/ uint8 buff_unknown; // if this is 4, a buff icon is made
/*0031*/ uint32 unknown0031; // seen 00 00 00 00
/*0035*/ uint8 unknown0035; // seen 00
/*0036*/ uint32 unknown0036; // seen ff ff ff ff
/*0040*/ uint32 unknown0040; // seen ff ff ff ff
/*0044*/ uint32 unknown0044; // seen ff ff ff ff
/*0048*/ uint32 unknown0048; // seen 00 00 00 00
/*0052*/ uint32 unknown0052; // seen 00 00 00 00
/*0056*/
};
@@ -1266,9 +1269,9 @@ struct CombatDamage_Struct
/* 05 */ uint16 spellid;
/* 07 */ int32 damage;
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float hit_heading; // see above notes in Action_Struct
/* 19 */ float hit_pitch;
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 28 */
};
@@ -3003,6 +3006,24 @@ struct GuildMakeLeader{
char target[64];
};
struct BugStruct{
/*0000*/ uint32 type1; //seems to be just a different way of seeing type; seems to be ordered completely differently
/*0004*/ char chartype[64];
/*0068*/ char name[96];
/*0164*/ char ui[128];
/*0292*/ float x;
/*0296*/ float y;
/*0300*/ float z;
/*0304*/ float heading;
/*0308*/ uint32 unknown304;
/*0312*/ char unknown308[160];
/*0472*/ char target_name[64];
/*0536*/ uint32 type;
/*0540*/ char unknown536[2052];
/*2588*/ char bug[2048];
/*4636*/ char unknown4632[6];
/*4642*/ char system_info[4094];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -3029,21 +3050,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -4380,22 +4400,6 @@ struct MercenaryAssign_Struct {
/*0004*/ uint32 MercUnk01; //
/*0008*/ uint32 MercUnk02; //
/*0012*/
};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char IsEvolving[1];
/*032*/ char EvolveGroup[4];
/*036*/ char EvolveLevel[1];
/*037*/ char OrnamentIcon[5];
/*042*/ char Hash[8];
/*050*/
};
}; /*structs*/
+46 -57
View File
@@ -53,11 +53,11 @@ namespace SoF
static inline uint32 SoFToServerSlot(uint32 sofSlot);
static inline uint32 SoFToServerCorpseSlot(uint32 sofCorpseSlot);
// server to client say link converter
static inline void ServerToSoFSayLink(std::string& sofSayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void SoFToServerSayLink(std::string& serverSayLink, const std::string& sofSayLink);
// client to server text link converter
static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink);
static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation);
@@ -161,14 +161,15 @@ namespace SoF
OUT(source);
OUT(level);
OUT(instrument_mod);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
eq->sequence = emu->sequence;
OUT(type);
//OUT(damage);
OUT(spell);
OUT(spell_level);
OUT(effect_flag); // if this is 4, a buff icon is made
eq->level2 = emu->level;
OUT(buff_unknown); // if this is 4, a buff icon is made
//eq->unknown0036 = -1;
//eq->unknown0040 = -1;
//eq->unknown0044 = -1;
FINISH_ENCODE();
}
@@ -327,7 +328,7 @@ namespace SoF
std::string old_message = emu->message;
std::string new_message;
ServerToSoFSayLink(new_message, old_message);
ServerToSoFTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -439,8 +440,8 @@ namespace SoF
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
FINISH_ENCODE();
}
@@ -612,7 +613,7 @@ namespace SoF
std::string old_message = emu->message;
std::string new_message;
ServerToSoFSayLink(new_message, old_message);
ServerToSoFTextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -664,7 +665,7 @@ namespace SoF
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToSoFSayLink(new_message_array[i], old_message_array[i]);
ServerToSoFTextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -1275,7 +1276,6 @@ namespace SoF
OUT(copper_cursor);
OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword)
OUT_array(InnateSkills, structs::MAX_PP_INNATE_SKILL); // 1:1 direct copy (25 dword)
// OUT(unknown04760[236]);
OUT(toxicity);
@@ -1813,7 +1813,7 @@ namespace SoF
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToSoFSayLink(new_message, old_message);
ServerToSoFTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -1881,7 +1881,7 @@ namespace SoF
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToSoFSayLink(new_message, old_message);
ServerToSoFTextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
@@ -2384,17 +2384,6 @@ namespace SoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
@@ -2414,7 +2403,7 @@ namespace SoF
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message;
SoFToServerSayLink(new_message, old_message);
SoFToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size];
@@ -2528,7 +2517,7 @@ namespace SoF
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
SoFToServerSayLink(new_message, old_message);
SoFToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -3315,19 +3304,19 @@ namespace SoF
return (sofCorpseSlot - 1);
}
static inline void ServerToSoFSayLink(std::string& sofSayLink, const std::string& serverSayLink)
static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
sofSayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
sofTextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
sofSayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
sofTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -3337,37 +3326,37 @@ namespace SoF
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
sofSayLink.push_back('\x12');
sofSayLink.append(segments[segment_iter].substr(0, 31));
sofSayLink.append(segments[segment_iter].substr(36, 5));
sofTextLink.push_back('\x12');
sofTextLink.append(segments[segment_iter].substr(0, 31));
sofTextLink.append(segments[segment_iter].substr(36, 5));
if (segments[segment_iter][41] == '0')
sofSayLink.push_back(segments[segment_iter][42]);
sofTextLink.push_back(segments[segment_iter][42]);
else
sofSayLink.push_back('F');
sofTextLink.push_back('F');
sofSayLink.append(segments[segment_iter].substr(43));
sofSayLink.push_back('\x12');
sofTextLink.append(segments[segment_iter].substr(43));
sofTextLink.push_back('\x12');
}
else {
sofSayLink.append(segments[segment_iter]);
sofTextLink.append(segments[segment_iter]);
}
}
}
static inline void SoFToServerSayLink(std::string& serverSayLink, const std::string& sofSayLink)
static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (sofSayLink.find('\x12') == std::string::npos)) {
serverSayLink = sofSayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sofTextLink.find('\x12') == std::string::npos)) {
serverTextLink = sofTextLink;
return;
}
auto segments = SplitString(sofSayLink, '\x12');
auto segments = SplitString(sofTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -3377,16 +3366,16 @@ namespace SoF
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter].substr(0, 31));
serverSayLink.append("00000");
serverSayLink.append(segments[segment_iter].substr(31, 5));
serverSayLink.push_back('0');
serverSayLink.append(segments[segment_iter].substr(36));
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter].substr(0, 31));
serverTextLink.append("00000");
serverTextLink.append(segments[segment_iter].substr(31, 5));
serverTextLink.push_back('0');
serverTextLink.append(segments[segment_iter].substr(36));
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
-1
View File
@@ -95,7 +95,6 @@ D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
+66 -122
View File
@@ -52,25 +52,6 @@ struct EnterWorld_Struct {
struct WorldObjectsSent_Struct {
};
// yep, even SoF had a version of the new inventory system, used by OP_MoveMultipleItems
struct InventorySlot_Struct
{
/*000*/ int32 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Trade = 3, World = 4, Limbo = 5
/*004*/ int32 Slot;
/*008*/ int32 SubIndex;
/*012*/ int32 AugIndex;
/*016*/ int32 Unknown01;
};
// unsure if they have a version of this, completeness though
struct TypelessInventorySlot_Struct
{
/*000*/ int32 Slot;
/*004*/ int32 SubIndex;
/*008*/ int32 AugIndex;
/*012*/ int32 Unknown01;
};
/* Name Approval Struct */
/* Len: */
/* Opcode: 0x8B20*/
@@ -326,8 +307,7 @@ union
/*0725*/ uint8 targetable; // 1 = Targetable 0 = Not Targetable (is_npc?)
/*0726*/ uint8 unknown0726[4];
/*0730*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
/*0731*/ float bounding_radius; // used in melee, overrides calc
/*0735*/ uint8 unknown0731[7];
/*0731*/ uint8 unknown0731[11];
/*0742*/ uint8 targetable_with_hotkey;
/*0743*/ signed padding00:12; // ***Placeholder
signed x:19; // x coord
@@ -819,7 +799,6 @@ static const uint32 MAX_PP_LANGUAGE = 25; //
static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now
static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;
@@ -924,8 +903,7 @@ struct PlayerProfile_Struct //23576 Octets
/*06488*/ uint32 silver_cursor; // Silver Pieces on cursor
/*06492*/ uint32 copper_cursor; // Copper Pieces on cursor
/*06496*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
/*06896*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL];
/*06996*/ uint8 unknown04760[36];
/*06896*/ uint8 unknown04760[136];
/*07032*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*07036*/ uint32 thirst_level; // Drink (ticks till next drink)
/*07040*/ uint32 hunger_level; // Food (ticks till next eat)
@@ -1215,18 +1193,20 @@ struct Action_Struct
{
/* 00 */ uint16 target; // id of target
/* 02 */ uint16 source; // id of caster
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/* 10 */ float force;
/* 14 */ float hit_heading;
/* 18 */ float hit_pitch;
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
/* 23 */ uint16 unknown23; // OSX says min_damage
/* 25 */ uint16 unknown25; // OSX says tohit
/* 04 */ uint16 level; // level of caster
/* 06 */ uint16 instrument_mod; // seems to be fixed to 0x0A
/* 08 */ uint32 unknown08;
/* 12 */ uint16 unknown16;
// some kind of sequence that's the same in both actions
// as well as the combat damage, to tie em together?
/* 14 */ float sequence; // was uint32
/* 18 */ uint32 unknown18;
/* 22 */ uint8 type; // 231 (0xE7) for spells
/* 23 */ uint32 unknown23;
/* 27 */ uint16 spell; // spell id being cast
/* 29 */ uint8 spell_level; // level of caster again? Or maybe the castee
/* 29 */ uint8 level2; // level of caster again? Or maybe the castee
// this field seems to be some sort of success flag, if it's 4
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
/* 31 */
};
@@ -1235,23 +1215,26 @@ struct Action_Struct
// has to do with buff blocking??
struct ActionAlt_Struct // ActionAlt_Struct - Size: 56 bytes
{
/*0000*/ uint16 target; // id of target
/*0002*/ uint16 source; // id of caster
/*0004*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*0006*/ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/*0010*/ float force;
/*0014*/ float hit_heading;
/*0018*/ float hit_pitch;
/*0022*/ uint8 type; // 231 (0xE7) for spells, skill
/*0023*/ uint16 unknown23; // OSX says min_damage
/*0025*/ uint16 unknown25; // OSX says tohit
/*0027*/ uint16 spell; // spell id being cast
/*0029*/ uint8 spell_level; // level of caster again? Or maybe the castee
// this field seems to be some sort of success flag, if it's 4
/*0030*/ uint8 effect_flag; // if this is 4, a buff icon is made
/*0031*/ uint8 spell_slot;
/*0032*/ uint32 slot[5];
/*0052*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
/*0000*/ uint16 target; // Target ID
/*0002*/ uint16 source; // SourceID
/*0004*/ uint16 level; // level of caster
/*0006*/ uint16 instrument_mod; // seems to be fixed to 0x0A
/*0008*/ uint32 unknown08;
/*0012*/ uint16 unknown16;
/*0014*/ uint32 sequence;
/*0018*/ uint32 unknown18;
/*0022*/ uint8 type; // Casts, Falls, Bashes, etc...
/*0023*/ uint32 damage; // Amount of Damage
/*0027*/ uint16 spell; // SpellID
/*0029*/ uint8 unknown29;
/*0030*/ uint8 buff_unknown; // if this is 4, a buff icon is made
/*0031*/ uint32 unknown0031; // seen 00 00 00 00
/*0035*/ uint8 unknown0035; // seen 00
/*0036*/ uint32 unknown0036; // seen ff ff ff ff
/*0040*/ uint32 unknown0040; // seen ff ff ff ff
/*0044*/ uint32 unknown0044; // seen ff ff ff ff
/*0048*/ uint32 unknown0048; // seen 00 00 00 00
/*0052*/ uint32 unknown0052; // seen 00 00 00 00
/*0056*/
};
@@ -1266,10 +1249,9 @@ struct CombatDamage_Struct
/* 05 */ uint16 spellid;
/* 07 */ int32 damage;
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float hit_heading; // see above notes in Action_Struct
/* 19 */ float hit_pitch;
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage, Report function doesn't seem to check this :P
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here?
/* 28 */
};
@@ -1573,19 +1555,6 @@ struct MoveItem_Struct
/*0012*/
};
struct MultiMoveItemSub_Struct
{
/*0000*/ InventorySlot_Struct from_slot;
/*0020*/ uint32 number_in_stack; // so the amount we are moving from the source
/*0024*/ InventorySlot_Struct to_slot;
};
struct MultiMoveItem_Struct
{
/*0000*/ uint32 count;
/*0004*/ MultiMoveItemSub_Struct moves[0];
};
//
// from_slot/to_slot
// -1 - destroy
@@ -2903,31 +2872,23 @@ struct GuildMakeLeader{
char target[64];
};
struct BugReport_Struct {
/*0000*/ char category_name[64];
/*0064*/ char character_name[64];
/*0128*/ char unused_0128[32];
/*0160*/ char ui_path[128];
/*0288*/ float pos_x;
/*0292*/ float pos_y;
/*0296*/ float pos_z;
/*0300*/ uint32 heading;
/*0304*/ uint32 unused_0304;
/*0308*/ uint32 time_played;
/*0312*/ char padding_0312[8];
/*0320*/ uint32 target_id;
/*0324*/ char padding_0324[140];
/*0464*/ uint32 unknown_0464; // seems to always be '0'
/*0468*/ char target_name[64];
/*0532*/ uint32 optional_info_mask;
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0536*/ char unused_0536[2052];
/*2588*/ char bug_report[2050];
/*4638*/ char system_info[4098];
/*8736*/
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -2954,21 +2915,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -4152,22 +4112,6 @@ struct AltCurrencySellItem_Struct {
/*004*/ uint32 slot_id;
/*006*/ uint32 charges;
/*010*/ uint32 cost;
};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char IsEvolving[1];
/*032*/ char EvolveGroup[4];
/*036*/ char EvolveLevel[1];
/*037*/ char OrnamentIcon[5];
/*042*/ char Hash[8];
/*050*/
};
}; /*structs*/
+44 -59
View File
@@ -52,11 +52,11 @@ namespace Titanium
static inline uint32 TitaniumToServerSlot(int16 titaniumSlot);
static inline uint32 TitaniumToServerCorpseSlot(int16 titaniumCorpseSlot);
// server to client say link converter
static inline void ServerToTitaniumSayLink(std::string& titaniumSayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void TitaniumToServerSayLink(std::string& serverSayLink, const std::string& titaniumSayLink);
// client to server text link converter
static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink);
static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation);
@@ -164,14 +164,11 @@ namespace Titanium
OUT(source);
OUT(level);
OUT(instrument_mod);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(sequence);
OUT(type);
//OUT(damage);
OUT(spell);
OUT(spell_level);
OUT(effect_flag); // if this is 4, a buff icon is made
OUT(buff_unknown); // if this is 4, a buff icon is made
FINISH_ENCODE();
}
@@ -293,7 +290,7 @@ namespace Titanium
std::string old_message = emu->message;
std::string new_message;
ServerToTitaniumSayLink(new_message, old_message);
ServerToTitaniumTextLink(new_message, old_message);
in->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -361,8 +358,8 @@ namespace Titanium
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
FINISH_ENCODE();
}
@@ -535,7 +532,7 @@ namespace Titanium
std::string old_message = emu->message;
std::string new_message;
ServerToTitaniumSayLink(new_message, old_message);
ServerToTitaniumTextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -577,7 +574,7 @@ namespace Titanium
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToTitaniumSayLink(new_message_array[i], old_message_array[i]);
ServerToTitaniumTextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -1023,7 +1020,6 @@ namespace Titanium
OUT(copper_cursor);
OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword)
OUT_array(InnateSkills, structs::MAX_PP_INNATE_SKILL); // 1:1 direct copy (25 dword)
// OUT(unknown04760[236]);
OUT(toxicity);
@@ -1405,7 +1401,7 @@ namespace Titanium
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToTitaniumSayLink(new_message, old_message);
ServerToTitaniumTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -1461,7 +1457,7 @@ namespace Titanium
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToTitaniumSayLink(new_message, old_message);
ServerToTitaniumTextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct) +
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct) +
@@ -1792,17 +1788,6 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);
@@ -1822,7 +1807,7 @@ namespace Titanium
std::string old_message = (char *)&__eq_buffer[sizeof(ChannelMessage_Struct)];
std::string new_message;
TitaniumToServerSayLink(new_message, old_message);
TitaniumToServerTextLink(new_message, old_message);
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
__packet->pBuffer = new unsigned char[__packet->size];
@@ -1894,7 +1879,7 @@ namespace Titanium
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
TitaniumToServerSayLink(new_message, old_message);
TitaniumToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -2488,19 +2473,19 @@ namespace Titanium
return titaniumCorpseSlot;
}
static inline void ServerToTitaniumSayLink(std::string& titaniumSayLink, const std::string& serverSayLink)
static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
titaniumSayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
titaniumTextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
titaniumSayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
titaniumTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -2510,37 +2495,37 @@ namespace Titanium
// 6.2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXXXXX (45)
// Diff: ^^^^^ ^ ^^^^^
titaniumSayLink.push_back('\x12');
titaniumSayLink.append(segments[segment_iter].substr(0, 31));
titaniumSayLink.append(segments[segment_iter].substr(36, 5));
titaniumTextLink.push_back('\x12');
titaniumTextLink.append(segments[segment_iter].substr(0, 31));
titaniumTextLink.append(segments[segment_iter].substr(36, 5));
if (segments[segment_iter][41] == '0')
titaniumSayLink.push_back(segments[segment_iter][42]);
titaniumTextLink.push_back(segments[segment_iter][42]);
else
titaniumSayLink.push_back('F');
titaniumTextLink.push_back('F');
titaniumSayLink.append(segments[segment_iter].substr(48));
titaniumSayLink.push_back('\x12');
titaniumTextLink.append(segments[segment_iter].substr(48));
titaniumTextLink.push_back('\x12');
}
else {
titaniumSayLink.append(segments[segment_iter]);
titaniumTextLink.append(segments[segment_iter]);
}
}
}
static inline void TitaniumToServerSayLink(std::string& serverSayLink, const std::string& titaniumSayLink)
static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (titaniumSayLink.find('\x12') == std::string::npos)) {
serverSayLink = titaniumSayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (titaniumTextLink.find('\x12') == std::string::npos)) {
serverTextLink = titaniumTextLink;
return;
}
auto segments = SplitString(titaniumSayLink, '\x12');
auto segments = SplitString(titaniumTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -2550,18 +2535,18 @@ namespace Titanium
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^ ^^^^^
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter].substr(0, 31));
serverSayLink.append("00000");
serverSayLink.append(segments[segment_iter].substr(31, 5));
serverSayLink.push_back('0');
serverSayLink.push_back(segments[segment_iter][36]);
serverSayLink.append("00000");
serverSayLink.append(segments[segment_iter].substr(37));
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter].substr(0, 31));
serverTextLink.append("00000");
serverTextLink.append(segments[segment_iter].substr(31, 5));
serverTextLink.push_back('0');
serverTextLink.push_back(segments[segment_iter][36]);
serverTextLink.append("00000");
serverTextLink.append(segments[segment_iter].substr(37));
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
-1
View File
@@ -78,7 +78,6 @@ D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
D(OP_AugmentItem)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)
+45 -102
View File
@@ -48,23 +48,6 @@ struct EnterWorld_Struct {
/*068*/ uint32 return_home; // 01 on "Return Home", 00 if not
};
// yep, even tit had a version of the new inventory system, used by OP_MoveMultipleItems
struct InventorySlot_Struct
{
/*000*/ int32 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Trade = 3, World = 4, Limbo = 5
/*004*/ int32 Slot;
/*008*/ int32 SubIndex; // no aug index in Tit
/*012*/ int32 Unknown01;
};
// unsure if they have a version of this, completeness though
struct TypelessInventorySlot_Struct
{
/*000*/ int32 Slot;
/*004*/ int32 SubIndex; // no aug index in Tit
/*008*/ int32 Unknown01;
};
/* Name Approval Struct */
/* Len: */
/* Opcode: 0x8B20*/
@@ -327,7 +310,7 @@ union
// horse: 0=brown, 1=white, 2=black, 3=tan
};
/*0340*/ uint32 spawnId; // Spawn Id
/*0344*/ float bounding_radius; // used in melee, overrides calc
/*0344*/ uint8 unknown0344[4];
/*0348*/ TintProfile equipment_tint;
/*0384*/ uint8 lfg; // 0=off, 1=lfg on
/*0385*/
@@ -757,7 +740,6 @@ static const uint32 MAX_PP_LANGUAGE = 28;
static const uint32 MAX_PP_SPELLBOOK = 400;
static const uint32 MAX_PP_MEMSPELL = 9;
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 240;
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;
@@ -862,8 +844,7 @@ struct PlayerProfile_Struct
/*04452*/ uint32 silver_cursor; // Silver Pieces on cursor
/*04456*/ uint32 copper_cursor; // Copper Pieces on cursor
/*04460*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
/*04860*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL];
/*04960*/ uint8 unknown04760[36];
/*04860*/ uint8 unknown04760[136];
/*04996*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*05000*/ uint32 thirst_level; // Drink (ticks till next drink)
/*05004*/ uint32 hunger_level; // Food (ticks till next eat)
@@ -1119,18 +1100,20 @@ struct Action_Struct
{
/* 00 */ uint16 target; // id of target
/* 02 */ uint16 source; // id of caster
/* 04 */ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/* 06 */ uint32 instrument_mod; // OSX dump says base damage, spells use it for bard song (different from newer clients)
/* 10 */ float force;
/* 14 */ float hit_heading;
/* 18 */ float hit_pitch;
/* 22 */ uint8 type; // 231 (0xE7) for spells, skill
/* 23 */ uint16 unknown23; // OSX says min_damage
/* 25 */ uint16 unknown25; // OSX says tohit
/* 04 */ uint16 level; // level of caster
/* 06 */ uint16 instrument_mod;
/* 08 */ uint32 unknown08;
/* 12 */ uint16 unknown16;
// some kind of sequence that's the same in both actions
// as well as the combat damage, to tie em together?
/* 14 */ uint32 sequence;
/* 18 */ uint32 unknown18;
/* 22 */ uint8 type; // 231 (0xE7) for spells
/* 23 */ uint32 unknown23;
/* 27 */ uint16 spell; // spell id being cast
/* 29 */ uint8 spell_level;
/* 29 */ uint8 unknown29;
// this field seems to be some sort of success flag, if it's 4
/* 30 */ uint8 effect_flag; // if this is 4, a buff icon is made
/* 30 */ uint8 buff_unknown; // if this is 4, a buff icon is made
/* 31 */
};
@@ -1141,12 +1124,12 @@ struct CombatDamage_Struct
{
/* 00 */ uint16 target;
/* 02 */ uint16 source;
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells, skill
/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells
/* 05 */ uint16 spellid;
/* 07 */ uint32 damage;
/* 11 */ float force;
/* 15 */ float hit_heading; // see above notes in Action_Struct
/* 19 */ float hit_pitch;
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */
};
@@ -1344,19 +1327,6 @@ struct MoveItem_Struct
/*0012*/
};
struct MultiMoveItemSub_Struct
{
/*0000*/ InventorySlot_Struct from_slot;
/*0016*/ uint32 number_in_stack; // so the amount we are moving from the source
/*0020*/ InventorySlot_Struct to_slot;
};
struct MultiMoveItem_Struct
{
/*0000*/ uint32 count;
/*0004*/ MultiMoveItemSub_Struct moves[0];
};
//
// from_slot/to_slot
// -1 - destroy
@@ -2569,32 +2539,21 @@ struct GuildMakeLeader{
char name[64];
char target[64];
};
struct BugReport_Struct {
/*0000*/ char category_name[64];
/*0064*/ char character_name[64];
/*0128*/ char unused_0128[32];
/*0160*/ char ui_path[128];
/*0288*/ float pos_x;
/*0292*/ float pos_y;
/*0296*/ float pos_z;
/*0300*/ uint32 heading;
/*0304*/ uint32 unused_0304;
/*0308*/ uint32 time_played;
/*0312*/ char padding_0312[8];
/*0320*/ uint32 target_id;
/*0324*/ char padding_0324[140];
/*0464*/ uint32 unknown_0464; // seems to always be '0'
/*0468*/ char target_name[64];
/*0532*/ uint32 optional_info_mask;
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0536*/ char unused_0536[2052];
/*2588*/ char bug_report[2050];
/*4638*/ char system_info[4098];
/*8736*/
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -2621,21 +2580,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -3563,21 +3521,6 @@ struct LFGuild_GuildToggle_Struct
// char ScrollName; // '0'
//};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char IsEvolving[1];
/*032*/ char EvolveGroup[4];
/*036*/ char EvolveLevel[1];
/*037*/ char Hash[8];
/*045*/
};
}; /*structs*/
}; /*Titanium*/
+64 -56
View File
@@ -53,11 +53,11 @@ namespace UF
static inline uint32 UFToServerSlot(uint32 ufSlot);
static inline uint32 UFToServerCorpseSlot(uint32 ufCorpseSlot);
// server to client say link converter
static inline void ServerToUFSayLink(std::string& ufSayLink, const std::string& serverSayLink);
// server to client text link converter
static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink);
// client to server say link converter
static inline void UFToServerSayLink(std::string& serverSayLink, const std::string& ufSayLink);
// client to server text link converter
static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink);
static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot);
static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot);
@@ -161,20 +161,29 @@ namespace UF
OUT(source);
OUT(level);
eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f;
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
eq->knockback_angle = emu->sequence;
OUT(type);
OUT(spell);
OUT(spell_level);
OUT(effect_flag);
eq->spell_gem = 0;
eq->slot[0] = -1; // type
eq->slot[1] = -1; // slot
eq->slot[2] = -1; // sub index
eq->slot[3] = -1; // aug index
eq->slot[4] = -1; // unknown
eq->item_cast_type = 0;
eq->level2 = eq->level;
eq->effect_flag = emu->buff_unknown;
eq->unknown37 = 0x01;
eq->unknown44 = 0xFFFFFFFF;
eq->unknown48 = 0xFFFFFFFF;
eq->unknown52 = 0xFFFFFFFF;
/*OUT(target);
OUT(source);
OUT(level);
OUT(instrument_mod);
eq->sequence = emu->sequence;
OUT(type);
//OUT(damage);
OUT(spell);
eq->level2 = emu->level;
OUT(buff_unknown); // if this is 4, a buff icon is made
//eq->unknown0036 = -1;
//eq->unknown0040 = -1;
//eq->unknown0044 = -1;*/
FINISH_ENCODE();
}
@@ -382,7 +391,7 @@ namespace UF
{
SETUP_VAR_ENCODE(BuffIcon_Struct);
uint32 sz = 12 + (17 * emu->count) + emu->name_lengths; // 17 includes nullterm
uint32 sz = 12 + (17 * emu->count);
__packet->size = sz;
__packet->pBuffer = new unsigned char[sz];
memset(__packet->pBuffer, 0, sz);
@@ -398,7 +407,7 @@ namespace UF
__packet->WriteUInt32(emu->entries[i].spell_id);
__packet->WriteUInt32(emu->entries[i].tics_remaining);
__packet->WriteUInt32(emu->entries[i].num_hits);
__packet->WriteString(emu->entries[i].caster);
__packet->WriteString("");
}
__packet->WriteUInt8(emu->type);
@@ -454,7 +463,7 @@ namespace UF
std::string old_message = emu->message;
std::string new_message;
ServerToUFSayLink(new_message, old_message);
ServerToUFTextLink(new_message, old_message);
//in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36;
in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39;
@@ -577,8 +586,8 @@ namespace UF
OUT(spellid);
OUT(damage);
OUT(force);
OUT(hit_heading);
OUT(hit_pitch);
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
FINISH_ENCODE();
@@ -753,7 +762,7 @@ namespace UF
std::string old_message = emu->message;
std::string new_message;
ServerToUFSayLink(new_message, old_message);
ServerToUFTextLink(new_message, old_message);
//if (new_message.length() > 512) // length restricted in packet building function due vari-length name size (no nullterm)
// new_message = new_message.substr(0, 512);
@@ -805,7 +814,7 @@ namespace UF
for (int i = 0; i < 9; ++i) {
if (old_message_array[i].length() == 0) { break; }
ServerToUFSayLink(new_message_array[i], old_message_array[i]);
ServerToUFTextLink(new_message_array[i], old_message_array[i]);
new_message_size += new_message_array[i].length() + 1;
}
@@ -1841,7 +1850,6 @@ namespace UF
OUT(copper_cursor);
OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword)
OUT_array(InnateSkills, structs::MAX_PP_INNATE_SKILL); // 1:1 direct copy (25 dword)
// OUT(unknown04760[236]);
OUT(toxicity);
@@ -2460,7 +2468,7 @@ namespace UF
std::string old_message = &emu->message[strlen(emu->sayer)];
std::string new_message;
ServerToUFSayLink(new_message, old_message);
ServerToUFTextLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1;
in->size = strlen(emu->sayer) + new_message.length() + 25;
@@ -2530,7 +2538,7 @@ namespace UF
std::string old_message = InBuffer; // start 'Reward' as string
std::string new_message;
ServerToUFSayLink(new_message, old_message);
ServerToUFTextLink(new_message, old_message);
in->size = sizeof(TaskDescriptionHeader_Struct) + sizeof(TaskDescriptionData1_Struct)+
sizeof(TaskDescriptionData2_Struct) + sizeof(TaskDescriptionTrailer_Struct)+
@@ -3278,7 +3286,7 @@ namespace UF
std::string old_message = InBuffer;
std::string new_message;
UFToServerSayLink(new_message, old_message);
UFToServerTextLink(new_message, old_message);
//__packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1;
__packet->size = sizeof(ChannelMessage_Struct) + new_message.length() + 1;
@@ -3389,7 +3397,7 @@ namespace UF
IN(type);
IN(spellid);
IN(damage);
IN(hit_heading);
IN(meleepush_xy);
FINISH_DIRECT_DECODE();
}
@@ -3412,7 +3420,7 @@ namespace UF
std::string old_message = (char *)&__eq_buffer[4]; // unknown01 offset
std::string new_message;
UFToServerSayLink(new_message, old_message);
UFToServerTextLink(new_message, old_message);
__packet->size = sizeof(Emote_Struct);
__packet->pBuffer = new unsigned char[__packet->size];
@@ -4281,19 +4289,19 @@ namespace UF
return (ufCorpseSlot - 1);
}
static inline void ServerToUFSayLink(std::string& ufSayLink, const std::string& serverSayLink)
static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink)
{
if ((constants::SayLinkBodySize == EQEmu::constants::SayLinkBodySize) || (serverSayLink.find('\x12') == std::string::npos)) {
ufSayLink = serverSayLink;
if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) {
ufTextLink = serverTextLink;
return;
}
auto segments = SplitString(serverSayLink, '\x12');
auto segments = SplitString(serverTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= EQEmu::constants::SayLinkBodySize) {
ufSayLink.append(segments[segment_iter]);
if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) {
ufTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -4303,37 +4311,37 @@ namespace UF
// SoF: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX X XXXXX XXXXXXXX (50)
// Diff: ^^^^^ ^
ufSayLink.push_back('\x12');
ufSayLink.append(segments[segment_iter].substr(0, 31));
ufSayLink.append(segments[segment_iter].substr(36, 5));
ufTextLink.push_back('\x12');
ufTextLink.append(segments[segment_iter].substr(0, 31));
ufTextLink.append(segments[segment_iter].substr(36, 5));
if (segments[segment_iter][41] == '0')
ufSayLink.push_back(segments[segment_iter][42]);
ufTextLink.push_back(segments[segment_iter][42]);
else
ufSayLink.push_back('F');
ufTextLink.push_back('F');
ufSayLink.append(segments[segment_iter].substr(43));
ufSayLink.push_back('\x12');
ufTextLink.append(segments[segment_iter].substr(43));
ufTextLink.push_back('\x12');
}
else {
ufSayLink.append(segments[segment_iter]);
ufTextLink.append(segments[segment_iter]);
}
}
}
static inline void UFToServerSayLink(std::string& serverSayLink, const std::string& ufSayLink)
static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink)
{
if ((EQEmu::constants::SayLinkBodySize == constants::SayLinkBodySize) || (ufSayLink.find('\x12') == std::string::npos)) {
serverSayLink = ufSayLink;
if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (ufTextLink.find('\x12') == std::string::npos)) {
serverTextLink = ufTextLink;
return;
}
auto segments = SplitString(ufSayLink, '\x12');
auto segments = SplitString(ufTextLink, '\x12');
for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) {
if (segment_iter & 1) {
if (segments[segment_iter].length() <= constants::SayLinkBodySize) {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
// TODO: log size mismatch error
continue;
}
@@ -4343,16 +4351,16 @@ namespace UF
// RoF2: X XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX XXXXX X XXXX XX XXXXX XXXXXXXX (56)
// Diff: ^^^^^ ^
serverSayLink.push_back('\x12');
serverSayLink.append(segments[segment_iter].substr(0, 31));
serverSayLink.append("00000");
serverSayLink.append(segments[segment_iter].substr(31, 5));
serverSayLink.push_back('0');
serverSayLink.append(segments[segment_iter].substr(36));
serverSayLink.push_back('\x12');
serverTextLink.push_back('\x12');
serverTextLink.append(segments[segment_iter].substr(0, 31));
serverTextLink.append("00000");
serverTextLink.append(segments[segment_iter].substr(31, 5));
serverTextLink.push_back('0');
serverTextLink.append(segments[segment_iter].substr(36));
serverTextLink.push_back('\x12');
}
else {
serverSayLink.append(segments[segment_iter]);
serverTextLink.append(segments[segment_iter]);
}
}
}
+65 -62
View File
@@ -292,7 +292,7 @@ struct Spawn_Struct
/*0000*/ //uint8 nullterm1; // hack to null terminate name
/*0064*/ uint32 spawnId;
/*0068*/ uint8 level;
/*0069*/ float bounding_radius; // used in melee, overrides calc
/*0069*/ float unknown1;
/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
Spawn_Struct_Bitfields Bitfields;
/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
@@ -848,7 +848,6 @@ static const uint32 MAX_PP_LANGUAGE = 25; //
static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now
static const uint32 MAX_PP_MEMSPELL = 12; //was 9 now 10 on Underfoot
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 300; //was 299
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;
@@ -955,8 +954,7 @@ struct PlayerProfile_Struct
/*07336*/ uint32 silver_cursor; // Silver Pieces on cursor
/*07340*/ uint32 copper_cursor; // Copper Pieces on cursor
/*07344*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
/*07744*/ uint32 InnateSkills[MAX_PP_INNATE_SKILL];
/*07844*/ uint8 unknown07644[36];
/*07744*/ uint8 unknown07644[136];
/*07880*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*07884*/ uint32 thirst_level; // Drink (ticks till next drink)
/*07888*/ uint32 hunger_level; // Food (ticks till next eat)
@@ -1252,19 +1250,19 @@ struct Action_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ uint16 instrument_focus;
/*12*/ uint16 unknown12; // seems to always be set to something and it doesn't change between casts except in special cases like changing instrument mods
/*14*/ uint32 unknown14; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint16 spell; // spell id being cast
/*35*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*35*/ uint8 level2; // level of caster again? Or maybe the castee
/*36*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*37*/
};
@@ -1276,22 +1274,27 @@ struct ActionAlt_Struct
{
/*00*/ uint16 target; // id of target
/*02*/ uint16 source; // id of caster
/*04*/ uint16 level; // level of caster for spells, OSX dump says attack rating, guess spells use it for level
/*06*/ uint32 unknown06; // OSX dump says base_damage, was used for bard mod too, this is 0'd :(
/*04*/ uint16 level; // level of caster - Seen 0
/*06*/ uint32 unknown06;
/*10*/ float instrument_mod;
/*14*/ float force;
/*18*/ float hit_heading;
/*22*/ float hit_pitch;
/*26*/ uint8 type; // 231 (0xE7) for spells, skill
/*27*/ uint32 damage; // OSX says min_damage
/*31*/ uint16 unknown31; // OSX says tohit
/*14*/ uint32 unknown14; // seen 0
/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again
/*22*/ uint32 unknown22;
/*26*/ uint8 type;
/*27*/ uint32 damage;
/*31*/ uint16 unknown31;
/*33*/ uint16 spell; // spell id being cast
/*35*/ uint8 spell_level; // level of caster again? Or maybe the castee
/*35*/ uint8 level2; // level of caster again? Or maybe the castee
/*36*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time?
/*37*/ uint8 spell_gem;
/*38*/ uint8 padding38[2];
/*40*/ uint32 slot[5];
/*60*/ uint32 item_cast_type; // ItemSpellTypes enum from MQ2
/*37*/ uint32 unknown37; // New field to Underfoot - Seen 14
/*41*/ uint8 unknown41; // New field to Underfoot - Seen 0
/*42*/ uint8 unknown42; // New field to Underfoot - Seen 0
/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0
/*44*/ uint32 unknown44; // New field to Underfoot - Seen 23
/*48*/ uint32 unknown48; // New field to Underfoot - Seen -1
/*52*/ uint32 unknown52; // New field to Underfoot - Seen -1
/*56*/ uint32 unknown56; // New field to Underfoot - Seen 0
/*60*/ uint32 unknown60; // New field to Underfoot - Seen 0
/*64*/
};
@@ -1306,9 +1309,9 @@ struct CombatDamage_Struct
/* 05 */ uint16 spellid;
/* 07 */ int32 damage;
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float hit_heading; // see above notes in Action_Struct
/* 19 */ float hit_pitch;
/* 23 */ uint8 secondary; // 0 for primary hand, 1 for secondary
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 28 */
};
@@ -3055,6 +3058,23 @@ struct GuildMakeLeader{
char target[64];
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@@ -3081,21 +3101,20 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
struct ApproveZone_Struct {
char name[64];
@@ -4484,22 +4503,6 @@ struct MercenaryAssign_Struct {
/*0004*/ uint32 MercUnk01; //
/*0008*/ uint32 MercUnk02; //
/*0012*/
};
struct SayLinkBodyFrame_Struct {
/*000*/ char ActionID[1];
/*001*/ char ItemID[5];
/*006*/ char Augment1[5];
/*011*/ char Augment2[5];
/*016*/ char Augment3[5];
/*021*/ char Augment4[5];
/*026*/ char Augment5[5];
/*031*/ char IsEvolving[1];
/*032*/ char EvolveGroup[4];
/*036*/ char EvolveLevel[1];
/*037*/ char OrnamentIcon[5];
/*042*/ char Hash[8];
/*050*/
};
}; /*structs*/
+2 -2
View File
@@ -28,9 +28,9 @@
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/global_define.h"
#include "../common/useperl.h"
#include "global_define.h"
#include "eqdb.h"
#include "useperl.h"
#ifdef THIS /* this macro seems to leak out on some systems */
#undef THIS
+2 -2
View File
@@ -28,9 +28,9 @@
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/global_define.h"
#include "../common/useperl.h"
#include "global_define.h"
#include "eqdb_res.h"
#include "useperl.h"
XS(XS_EQDBRes_num_rows); /* prototype to pass -Wmissing-prototypes */
+11 -27
View File
@@ -44,7 +44,6 @@ RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this wi
RULE_INT(Character, DeathItemLossLevel, 10)
RULE_INT(Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost
RULE_BOOL(Character, UseDeathExpLossMult, false) //Adjust to use the above multiplier or to use code default.
RULE_BOOL(Character, UseOldRaceRezEffects, false) // older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore
RULE_INT(Character, CorpseDecayTimeMS, 10800000)
RULE_INT(Character, CorpseResTimeMS, 10800000) // time before cant res corpse(3 hours)
RULE_BOOL(Character, LeaveCorpses, true)
@@ -67,12 +66,11 @@ RULE_INT(Character, AutosaveIntervalS, 300) //0=disabled
RULE_INT(Character, HPRegenMultiplier, 100)
RULE_INT(Character, ManaRegenMultiplier, 100)
RULE_INT(Character, EnduranceRegenMultiplier, 100)
RULE_BOOL(Character, OldMinMana, false) // this is used for servers that want to follow older skill cap formulas so they can still have some regen w/o mediate
RULE_INT(Character, ConsumptionMultiplier, 100) //item's hunger restored = this value * item's food level, 100 = normal, 50 = people eat 2x as fast, 200 = people eat 2x as slow
RULE_BOOL(Character, HealOnLevel, false)
RULE_BOOL(Character, FeignKillsPet, false)
RULE_INT(Character, ItemManaRegenCap, 15)
RULE_INT(Character, ItemHealthRegenCap, 30)
RULE_INT(Character, ItemHealthRegenCap, 35)
RULE_INT(Character, ItemDamageShieldCap, 30)
RULE_INT(Character, ItemAccuracyCap, 150)
RULE_INT(Character, ItemAvoidanceCap, 100)
@@ -93,12 +91,10 @@ RULE_INT(Character, HasteCap, 100) // Haste cap for non-v3(overhaste) haste.
RULE_INT(Character, SkillUpModifier, 100) //skill ups are at 100%
RULE_BOOL(Character, SharedBankPlat, false) //off by default to prevent duping for now
RULE_BOOL(Character, BindAnywhere, false)
RULE_BOOL(Character, RestRegenEnabled, true) // Enable OOC Regen
RULE_INT(Character, RestRegenHP, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
RULE_INT(Character, RestRegenMana, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
RULE_INT(Character, RestRegenEnd, 180) // seconds until full from 0. this is actually zone setable, but most or all zones are 180
RULE_INT(Character, RestRegenPercent, 0) // Set to >0 to enable rest state bonus HP and mana regen.
RULE_INT(Character, RestRegenTimeToActivate, 30) // Time in seconds for rest state regen to kick in.
RULE_INT(Character, RestRegenRaidTimeToActivate, 300) // Time in seconds for rest state regen to kick in with a raid target.
RULE_BOOL(Character, RestRegenEndurance, false) // Whether rest regen will work for endurance or not.
RULE_INT(Character, KillsPerGroupLeadershipAA, 250) // Number of dark blues or above per Group Leadership AA
RULE_INT(Character, KillsPerRaidLeadershipAA, 250) // Number of dark blues or above per Raid Leadership AA
RULE_INT(Character, MaxFearDurationForPlayerCharacter, 4) //4 tics, each tic calculates every 6 seconds.
@@ -121,8 +117,7 @@ RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVEN
RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients.
RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients.
RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap
RULE_INT(Character, FoodLossPerUpdate, 32) // How much food/water you lose per stamina update
RULE_BOOL(Character, EnableHungerPenalties, false) // being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties
RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update
RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well.
RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field
RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225.
@@ -156,7 +151,6 @@ RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound beh
RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, OPClientUpdateVisualDebug, false) // Shows a pulse and forward directional particle each time the client sends its position to server
RULE_BOOL(Character, PetsUseReagents, true) //Pets use reagent on spells
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -192,14 +186,12 @@ RULE_INT(Skills, MaxTrainSpecializations, 50) // Max level a GM trainer will tra
RULE_INT(Skills, SwimmingStartValue, 100)
RULE_BOOL(Skills, TrainSenseHeading, false)
RULE_INT(Skills, SenseHeadingStartValue, 200)
RULE_BOOL(Skills, SelfLanguageLearning, true)
RULE_CATEGORY_END()
RULE_CATEGORY(Pets)
RULE_REAL(Pets, AttackCommandRange, 150)
RULE_BOOL(Pets, UnTargetableSwarmPet, false)
RULE_REAL(Pets, PetPowerLevelCap, 10) // Max number of levels your pet can go up with pet power
RULE_BOOL(Pets, CanTakeNoDrop, false) // Can everyone trade nodrop gear to pets
RULE_CATEGORY_END()
RULE_CATEGORY(GM)
@@ -234,7 +226,6 @@ RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium C
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
RULE_INT(World, PVPMinLevel, 0) // minimum level to pvp
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
RULE_BOOL (World, IPLimitDisconnectAll, false)
@@ -277,10 +268,17 @@ RULE_INT(Zone, GlobalLootMultiplier, 1) // Sets Global Loot drop multiplier for
RULE_CATEGORY_END()
RULE_CATEGORY(Map)
//enable these to help prevent mob hopping when they are pathing
RULE_BOOL(Map, FixPathingZWhenLoading, true) //increases zone boot times a bit to reduce hopping.
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, 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, 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, FixPathingZMaxDeltaLoading, 45) //while loading each waypoint: max change in Z to allow the BestZ code to apply.
RULE_INT(Map, FindBestZHeightAdjust, 1) // Adds this to the current Z before seeking the best Z position
RULE_CATEGORY_END()
@@ -402,7 +400,6 @@ RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spr
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, OldRainTargets, false) // use old incorrectly implemented max targets for rains
RULE_BOOL(Spells, NPCSpellPush, false) // enable spell push on NPCs
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)
@@ -505,7 +502,6 @@ RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will tak
RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF
RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't
RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system
RULE_BOOL(Combat, ClassicNPCBackstab, false) // true disables npc facestab - npcs get normal attack if not behind
RULE_CATEGORY_END()
RULE_CATEGORY(NPC)
@@ -672,12 +668,6 @@ RULE_CATEGORY_END()
RULE_CATEGORY(AA)
RULE_INT(AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52.
RULE_BOOL(AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients.
RULE_BOOL(AA, NormalizedAAEnabled, false) // TSS+ change to AA that normalizes AA XP to a fixed # of white con kills independent of level.
RULE_INT(AA, NormalizedAANumberOfWhiteConPerAA, 25) // The number of white con kills per AA point.
RULE_BOOL(AA, ModernAAScalingEnabled, false) // Are we linearly scaling AA XP based on total # of earned AA?
RULE_REAL(AA, ModernAAScalingStartPercent, 1000) // 1000% or 10x AA XP at the start of the scaling range
RULE_INT(AA, ModernAAScalingAAMinimum, 0) // The minimum number of earned AA before AA XP scaling begins.
RULE_INT(AA, ModernAAScalingAALimit, 4000) // The number of earned AA when AA XP scaling ends
RULE_CATEGORY_END()
RULE_CATEGORY(Console)
@@ -723,12 +713,6 @@ RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction
RULE_BOOL(Client, UseLiveBlockedMessage, false) // Allows players to see faction adjustments like Live
RULE_CATEGORY_END()
RULE_CATEGORY(Bugs)
RULE_BOOL(Bugs, ReportingSystemActive, true) // Activates bug reporting
RULE_BOOL(Bugs, UseOldReportingMethod, true) // Forces the use of the old bug reporting system
RULE_BOOL(Bugs, DumpTargetEntity, false) // Dumps the target entity, if one is provided
RULE_CATEGORY_END()
#undef RULE_CATEGORY
#undef RULE_INT
#undef RULE_REAL
+53 -51
View File
@@ -29,10 +29,10 @@
bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body)
{
memset(&say_link_body_struct, 0, sizeof(say_link_body_struct));
if (say_link_body.length() != EQEmu::constants::SayLinkBodySize)
if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH)
return false;
say_link_body_struct.action_id = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16);
say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16);
say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16);
say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16);
@@ -44,7 +44,7 @@ bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct
say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16);
say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16);
say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16);
say_link_body_struct.hash = (uint32)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
say_link_body_struct.hash = (int)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16);
return true;
}
@@ -53,7 +53,7 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB
{
say_link_body = StringFormat(
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
(0x0F & say_link_body_struct.action_id),
(0x0F & say_link_body_struct.unknown_1),
(0x000FFFFF & say_link_body_struct.item_id),
(0x000FFFFF & say_link_body_struct.augment_1),
(0x000FFFFF & say_link_body_struct.augment_2),
@@ -68,7 +68,7 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB
(0xFFFFFFFF & say_link_body_struct.hash)
);
if (say_link_body.length() != EQEmu::constants::SayLinkBodySize)
if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH)
return false;
return true;
@@ -79,7 +79,7 @@ EQEmu::SayLinkEngine::SayLinkEngine()
Reset();
}
const std::string& EQEmu::SayLinkEngine::GenerateLink()
std::string EQEmu::SayLinkEngine::GenerateLink()
{
m_Link.clear();
m_LinkBody.clear();
@@ -88,26 +88,18 @@ const std::string& EQEmu::SayLinkEngine::GenerateLink()
generate_body();
generate_text();
if ((m_LinkBody.length() == EQEmu::constants::SayLinkBodySize) && (m_LinkText.length() > 0)) {
if ((m_LinkBody.length() == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) {
m_Link.push_back(0x12);
m_Link.append(m_LinkBody);
m_Link.append(m_LinkText);
m_Link.push_back(0x12);
}
if ((m_Link.length() == 0) || (m_Link.length() > (EQEmu::constants::SayLinkMaximumSize))) {
if ((m_Link.length() == 0) || (m_Link.length() > 250)) {
m_Error = true;
m_Link = "<LINKER ERROR>";
Log(Logs::General, Logs::Error, "SayLinkEngine::GenerateLink() failed to generate a useable say link");
Log(Logs::General, Logs::Error, ">> LinkType: %i, Lengths: {link: %u(%u), body: %u(%u), text: %u(%u)}",
m_LinkType,
m_Link.length(),
EQEmu::constants::SayLinkMaximumSize,
m_LinkBody.length(),
EQEmu::constants::SayLinkBodySize,
m_LinkText.length(),
EQEmu::constants::SayLinkTextSize
);
Log(Logs::General, Logs::Error, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})",
m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length());
Log(Logs::General, Logs::Error, ">> LinkBody: %s", m_LinkBody.c_str());
Log(Logs::General, Logs::Error, ">> LinkText: %s", m_LinkText.c_str());
}
@@ -121,10 +113,20 @@ void EQEmu::SayLinkEngine::Reset()
m_ItemData = nullptr;
m_LootData = nullptr;
m_ItemInst = nullptr;
memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct));
memset(&m_LinkProxyStruct, 0, sizeof(SayLinkProxy_Struct));
m_Proxy_unknown_1 = 0;
m_ProxyItemID = 0;
m_ProxyAugment1ID = 0;
m_ProxyAugment2ID = 0;
m_ProxyAugment3ID = 0;
m_ProxyAugment4ID = 0;
m_ProxyAugment5ID = 0;
m_ProxyAugment6ID = 0;
m_ProxyIsEvolving = 0;
m_ProxyEvolveGroup = 0;
m_ProxyEvolveLevel = 0;
m_ProxyOrnamentIcon = 0;
m_ProxyHash = 0;
m_ProxyText = nullptr;
m_TaskUse = false;
m_Link.clear();
m_LinkBody.clear();
@@ -192,32 +194,32 @@ void EQEmu::SayLinkEngine::generate_body()
break;
}
if (m_LinkProxyStruct.action_id)
m_LinkBodyStruct.action_id = m_LinkProxyStruct.action_id;
if (m_LinkProxyStruct.item_id)
m_LinkBodyStruct.item_id = m_LinkProxyStruct.item_id;
if (m_LinkProxyStruct.augment_1)
m_LinkBodyStruct.augment_1 = m_LinkProxyStruct.augment_1;
if (m_LinkProxyStruct.augment_2)
m_LinkBodyStruct.augment_2 = m_LinkProxyStruct.augment_2;
if (m_LinkProxyStruct.augment_3)
m_LinkBodyStruct.augment_3 = m_LinkProxyStruct.augment_3;
if (m_LinkProxyStruct.augment_4)
m_LinkBodyStruct.augment_4 = m_LinkProxyStruct.augment_4;
if (m_LinkProxyStruct.augment_5)
m_LinkBodyStruct.augment_5 = m_LinkProxyStruct.augment_5;
if (m_LinkProxyStruct.augment_6)
m_LinkBodyStruct.augment_6 = m_LinkProxyStruct.augment_6;
if (m_LinkProxyStruct.is_evolving)
m_LinkBodyStruct.is_evolving = m_LinkProxyStruct.is_evolving;
if (m_LinkProxyStruct.evolve_group)
m_LinkBodyStruct.evolve_group = m_LinkProxyStruct.evolve_group;
if (m_LinkProxyStruct.evolve_level)
m_LinkBodyStruct.evolve_level = m_LinkProxyStruct.evolve_level;
if (m_LinkProxyStruct.ornament_icon)
m_LinkBodyStruct.ornament_icon = m_LinkProxyStruct.ornament_icon;
if (m_LinkProxyStruct.hash)
m_LinkBodyStruct.hash = m_LinkProxyStruct.hash;
if (m_Proxy_unknown_1)
m_LinkBodyStruct.unknown_1 = m_Proxy_unknown_1;
if (m_ProxyItemID)
m_LinkBodyStruct.item_id = m_ProxyItemID;
if (m_ProxyAugment1ID)
m_LinkBodyStruct.augment_1 = m_ProxyAugment1ID;
if (m_ProxyAugment2ID)
m_LinkBodyStruct.augment_2 = m_ProxyAugment2ID;
if (m_ProxyAugment3ID)
m_LinkBodyStruct.augment_3 = m_ProxyAugment3ID;
if (m_ProxyAugment4ID)
m_LinkBodyStruct.augment_4 = m_ProxyAugment4ID;
if (m_ProxyAugment5ID)
m_LinkBodyStruct.augment_5 = m_ProxyAugment5ID;
if (m_ProxyAugment6ID)
m_LinkBodyStruct.augment_6 = m_ProxyAugment6ID;
if (m_ProxyIsEvolving)
m_LinkBodyStruct.is_evolving = m_ProxyIsEvolving;
if (m_ProxyEvolveGroup)
m_LinkBodyStruct.evolve_group = m_ProxyEvolveGroup;
if (m_ProxyEvolveLevel)
m_LinkBodyStruct.evolve_level = m_ProxyEvolveLevel;
if (m_ProxyOrnamentIcon)
m_LinkBodyStruct.ornament_icon = m_ProxyOrnamentIcon;
if (m_ProxyHash)
m_LinkBodyStruct.hash = m_ProxyHash;
if (m_TaskUse)
@@ -225,7 +227,7 @@ void EQEmu::SayLinkEngine::generate_body()
m_LinkBody = StringFormat(
"%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X",
(0x0F & m_LinkBodyStruct.action_id),
(0x0F & m_LinkBodyStruct.unknown_1),
(0x000FFFFF & m_LinkBodyStruct.item_id),
(0x000FFFFF & m_LinkBodyStruct.augment_1),
(0x000FFFFF & m_LinkBodyStruct.augment_2),
@@ -243,8 +245,8 @@ void EQEmu::SayLinkEngine::generate_body()
void EQEmu::SayLinkEngine::generate_text()
{
if (m_LinkProxyStruct.text != nullptr) {
m_LinkText = m_LinkProxyStruct.text;
if (m_ProxyText != nullptr) {
m_LinkText = m_ProxyText;
return;
}
+37 -28
View File
@@ -47,7 +47,7 @@ namespace EQEmu
} /*saylink*/
struct SayLinkBody_Struct {
uint8 action_id; /* %1X */
uint8 unknown_1; /* %1X */
uint32 item_id; /* %05X */
uint32 augment_1; /* %05X */
uint32 augment_2; /* %05X */
@@ -56,18 +56,13 @@ namespace EQEmu
uint32 augment_5; /* %05X */
uint32 augment_6; /* %05X */
uint8 is_evolving; /* %1X */
uint32 evolve_group; /* %04X */
uint32 evolve_group; /* %05X */
uint8 evolve_level; /* %02X */
uint32 ornament_icon; /* %05X */
uint32 hash; /* %08X */
};
struct SayLinkProxy_Struct : SayLinkBody_Struct {
const char* text;
int hash; /* %08X */
};
class SayLinkEngine {
// TODO: consider methods for direct 'saylink' assignments
public:
SayLinkEngine();
@@ -77,29 +72,29 @@ namespace EQEmu
void SetItemInst(const ItemInstance* item_inst) { m_ItemInst = item_inst; }
// mainly for saylinks..but, not limited to
void SetProxyActionID(uint8 proxy_action_id) { m_LinkProxyStruct.action_id = proxy_action_id; } // should always be '0'
void SetProxyItemID(uint32 proxy_item_id) { m_LinkProxyStruct.item_id = proxy_item_id; }
void SetProxyAugment1ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_1 = proxy_augment_id; }
void SetProxyAugment2ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_2 = proxy_augment_id; }
void SetProxyAugment3ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_3 = proxy_augment_id; }
void SetProxyAugment4ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_4 = proxy_augment_id; }
void SetProxyAugment5ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_5 = proxy_augment_id; }
void SetProxyAugment6ID(uint32 proxy_augment_id) { m_LinkProxyStruct.augment_6 = proxy_augment_id; }
void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_LinkProxyStruct.is_evolving = proxy_is_evolving; }
void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_LinkProxyStruct.evolve_group = proxy_evolve_group; }
void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_LinkProxyStruct.evolve_level = proxy_evolve_level; }
void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_LinkProxyStruct.ornament_icon = proxy_ornament_icon; }
void SetProxyHash(uint32 proxy_hash) { m_LinkProxyStruct.hash = proxy_hash; }
void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; }
void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; }
void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; }
void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; }
void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; }
void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; }
void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; }
void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; }
void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; }
void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; }
void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; }
void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; }
void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; }
void SetProxyText(const char* proxy_text) { m_LinkProxyStruct.text = proxy_text; } // overrides standard text use
void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use
void SetTaskUse() { m_TaskUse = true; }
const std::string& GenerateLink();
std::string GenerateLink();
bool LinkError() { return m_Error; }
const std::string& Link() { return m_Link; } // contains full string format: '\x12' '<LinkBody>' '<LinkText>' '\x12'
const std::string& LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
const std::string& LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
std::string Link() { return m_Link; } // contains full string format: '/12x' '<LinkBody>' '<LinkText>' '/12x'
std::string LinkBody() { return m_LinkBody; } // contains string format: '<LinkBody>'
std::string LinkText() { return m_LinkText; } // contains string format: '<LinkText>'
void Reset();
@@ -111,9 +106,23 @@ namespace EQEmu
const ItemData* m_ItemData;
const ServerLootItem_Struct* m_LootData;
const ItemInstance* m_ItemInst;
SayLinkBody_Struct m_LinkBodyStruct;
SayLinkProxy_Struct m_LinkProxyStruct;
uint8 m_Proxy_unknown_1;
uint32 m_ProxyItemID;
uint32 m_ProxyAugment1ID;
uint32 m_ProxyAugment2ID;
uint32 m_ProxyAugment3ID;
uint32 m_ProxyAugment4ID;
uint32 m_ProxyAugment5ID;
uint32 m_ProxyAugment6ID;
uint8 m_ProxyIsEvolving;
uint32 m_ProxyEvolveGroup;
uint8 m_ProxyEvolveLevel;
uint32 m_ProxyOrnamentIcon;
int m_ProxyHash;
const char* m_ProxyText;
bool m_TaskUse;
SayLinkBody_Struct m_LinkBodyStruct;
std::string m_Link;
std::string m_LinkBody;
std::string m_LinkText;
-13
View File
@@ -190,8 +190,6 @@
#define ServerOP_ReloadLogs 0x4010
#define ServerOP_ReloadPerlExportSettings 0x4011
#define ServerOP_CZSetEntityVariableByClientName 0x4012
#define ServerOP_UCSServerStatusRequest 0x4013
#define ServerOP_UCSServerStatusReply 0x4014
/* Query Server OP Codes */
#define ServerOP_QSPlayerLogTrades 0x5010
#define ServerOP_QSPlayerLogHandins 0x5011
@@ -1280,17 +1278,6 @@ struct ServerRequestTellQueue_Struct {
char name[64];
};
struct UCSServerStatus_Struct {
uint8 available; // non-zero=true, 0=false
union {
struct {
uint16 port;
uint16 unused;
};
uint32 timestamp;
};
};
#pragma pack()
#endif
+2 -37
View File
@@ -110,41 +110,6 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
return EntitledTime;
}
void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey)
{
char MailKeyString[17];
if (RuleB(Chat, EnableMailKeyIPVerification) == true)
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
else
sprintf(MailKeyString, "%08X", MailKey);
std::string query = StringFormat("UPDATE character_data SET mailkey = '%s' WHERE id = '%i'",
MailKeyString, CharID);
auto results = QueryDatabase(query);
if (!results.Success())
Log(Logs::General, Logs::Error, "SharedDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, results.ErrorMessage().c_str());
}
std::string SharedDatabase::GetMailKey(int CharID, bool key_only)
{
std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", CharID);
auto results = QueryDatabase(query);
if (!results.Success()) {
Log(Logs::Detail, Logs::MySQLError, "Error retrieving mailkey from database: %s", results.ErrorMessage().c_str());
return std::string();
}
auto row = results.begin();
std::string mail_key = row[0];
if (mail_key.length() > 8 && key_only)
return mail_key.substr(8);
else
return mail_key;
}
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<EQEmu::ItemInstance*>::const_iterator &start, std::list<EQEmu::ItemInstance*>::const_iterator &end)
{
// Delete cursor items
@@ -1852,8 +1817,8 @@ void SharedDatabase::LoadBaseData(void *data, int max_level) {
bd->base_hp = atof(row[2]);
bd->base_mana = atof(row[3]);
bd->base_end = atof(row[4]);
bd->hp_regen = atof(row[5]);
bd->end_regen = atof(row[6]);
bd->unk1 = atof(row[5]);
bd->unk2 = atof(row[6]);
bd->hp_factor = atof(row[7]);
bd->mana_factor = atof(row[8]);
bd->endurance_factor = atof(row[9]);
-2
View File
@@ -72,8 +72,6 @@ class SharedDatabase : public Database
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
void SetMailKey(int CharID, int IPAddress, int MailKey);
std::string GetMailKey(int CharID, bool key_only = false);
/*
Character InventoryProfile
+1 -7
View File
@@ -73,8 +73,6 @@ enum SpellTypes : uint32
SpellTypes_Detrimental = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow),
SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong | SpellType_PreCombatBuff | SpellType_PreCombatBuffSong),
SpellTypes_Innate = (SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root),
SpellType_Any = 0xFFFFFFFF
};
@@ -133,11 +131,6 @@ enum SpellAffectIndex {
SAI_NPC_Special_80 = 80,
SAI_Trap_Lock = 88
};
enum class GlobalGroup {
Lich = 46,
};
enum RESISTTYPE
{
RESIST_NONE = 0,
@@ -972,6 +965,7 @@ bool IsCastWhileInvis(uint16 spell_id);
bool IsEffectIgnoredInStacking(int spa);
int CalcPetHp(int levelb, int classb, int STA = 75);
const char *GetRandPetName();
int GetSpellEffectDescNum(uint16 spell_id);
DmgShieldType GetDamageShieldType(uint16 spell_id, int32 DSType = 0);
bool DetrimentalSpellAllowsRest(uint16 spell_id);
+2 -2
View File
@@ -30,9 +30,9 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9122
#define CURRENT_BINARY_DATABASE_VERSION 9114
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9018
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif
+2 -1
View File
@@ -3,4 +3,5 @@ IF(EQEMU_BUILD_LUA)
ENDIF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(libuv)
ADD_SUBDIRECTORY(format)
ADD_SUBDIRECTORY(format)
ADD_SUBDIRECTORY(recast)
+3
View File
@@ -0,0 +1,3 @@
<!---
Please make sure you've followed the guidelines outlined in the CONTRIBUTING.rst file.
--->
+19
View File
@@ -0,0 +1,19 @@
bin/
/_CPack_Packages
/doc/doxyxml
/doc/html
virtualenv
/Testing
/install_manifest.txt
*~
*.a
*.so*
*.zip
cmake_install.cmake
CPack*.cmake
fmt-*.cmake
CTestTestfile.cmake
CMakeCache.txt
CMakeFiles
Makefile
run-msbuild.bat
+1 -7
View File
@@ -1,4 +1,5 @@
language: cpp
dist: trusty
sudo: required # the doc target uses sudo to install dependencies
os:
@@ -22,12 +23,5 @@ matrix:
- os: osx
env: BUILD=Doc
addons:
apt:
sources:
- kubuntu-backports # cmake 2.8.12
packages:
- cmake
script:
- support/travis-build.py
+23 -9
View File
@@ -1,6 +1,6 @@
message(STATUS "CMake version: ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 2.8.12)
# Determine if fmt is built as a subproject (using add_subdirectory)
# or if it is the master project.
@@ -9,12 +9,22 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
endif ()
# Joins arguments and places the results in ${result_var}.
function(join result_var)
set(result )
foreach (arg ${ARGN})
set(result "${result}${arg}")
endforeach ()
set(${result_var} "${result}" PARENT_SCOPE)
endfunction()
# Set the default CMAKE_BUILD_TYPE to Release.
# This should be done before the project command since the latter can set
# CMAKE_BUILD_TYPE itself (it does so for nmake).
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
join(doc "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
set(CMAKE_BUILD_TYPE Release CACHE STRING ${doc})
endif ()
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
@@ -28,13 +38,17 @@ option(FMT_USE_CPP11 "Enable the addition of C++11 compiler flags." ON)
project(FMT)
# Starting with cmake 3.0 VERSION is part of the project command.
set(FMT_VERSION 3.0.0)
if (NOT FMT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
message(FATAL_ERROR "Invalid version format ${FMT_VERSION}.")
file(READ fmt/format.h format_h)
if (NOT format_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
message(FATAL_ERROR "Cannot get FMT_VERSION from format.h.")
endif ()
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
# Use math to skip leading zeros if any.
math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
${CPACK_PACKAGE_VERSION_PATCH})
message(STATUS "Version: ${FMT_VERSION}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+11
View File
@@ -0,0 +1,11 @@
Contributing to fmt
===================
All C++ code must adhere to `Google C++ Style Guide
<https://google.github.io/styleguide/cppguide.html>`_ with the following
exceptions:
* Exceptions are permitted
* snake_case should be used instead of UpperCamelCase for function names
Thanks for contributing!
+110
View File
@@ -1,3 +1,113 @@
4.0.0 - 2017-06-27
------------------
* Removed old compatibility headers ``cppformat/*.h`` and CMake options (`#527 <https://github.com/pull/527>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
* Added ``string.h`` containing ``fmt::to_string()`` as alternative to ``std::to_string()`` as well as other string writer functionality (`#326 <https://github.com/fmtlib/fmt/issues/326>`_ and `#441 <https://github.com/fmtlib/fmt/pull/441>`_):
.. code:: c++
#include "fmt/string.h"
std::string answer = fmt::to_string(42);
Thanks to `@glebov-andrey (Andrey Glebov) <https://github.com/glebov-andrey>`_.
* Moved ``fmt::printf()`` to new ``printf.h`` header and allowed ``%s`` as generic specifier (`#453 <https://github.com/fmtlib/fmt/pull/453>`_), made ``%.f`` more conformant to regular ``printf()`` (`#490 <https://github.com/fmtlib/fmt/pull/490>`_), added custom writer support (`#476 <https://github.com/fmtlib/fmt/issues/476>`_) and implemented missing custom argument formatting (`#339 <https://github.com/fmtlib/fmt/pull/339>`_ and `#340 <https://github.com/fmtlib/fmt/pull/340>`_):
.. code:: c++
#include "fmt/printf.h"
// %s format specifier can be used with any argument type.
fmt::printf("%s", 42);
Thanks `@mojoBrendan <https://github.com/mojoBrendan>`_, `@manylegged (Arthur Danskin) <https://github.com/manylegged>`_ and `@spacemoose (Glen Stark) <https://github.com/spacemoose>`_. See also `#360 <https://github.com/fmtlib/fmt/issues/360>`_, `#335 <https://github.com/fmtlib/fmt/issues/335>`_ and `#331 <https://github.com/fmtlib/fmt/issues/331>`_.
* Added ``container.h`` containing a ``BasicContainerWriter`` to write to containers like ``std::vector`` (`#450 <https://github.com/fmtlib/fmt/pull/450>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_.
* Added ``fmt::join()`` function that takes a range and formats its elements separated by a given string (`#466 <https://github.com/fmtlib/fmt/pull/466>`_):
.. code:: c++
#include "fmt/format.h"
std::vector<double> v = {1.2, 3.4, 5.6};
// Prints "(+01.20, +03.40, +05.60)".
fmt::print("({:+06.2f})", fmt::join(v.begin(), v.end(), ", "));
Thanks `@olivier80 <https://github.com/olivier80>`_.
* Added support for custom formatting specifications to simplify customization of built-in formatting (`#444 <https://github.com/fmtlib/fmt/pull/444>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_. See also `#439 <https://github.com/fmtlib/fmt/issues/439>`_.
* Added ``fmt::format_system_error()`` for error code formatting (`#323 <https://github.com/fmtlib/fmt/issues/323>`_ and `#526 <https://github.com/fmtlib/fmt/pull/526>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
* Added thread-safe ``fmt::localtime()`` and ``fmt::gmtime()`` as replacement for the standard version to ``time.h`` (`#396 <https://github.com/fmtlib/fmt/pull/396>`_). Thanks `@codicodi <https://github.com/codicodi>`_.
* Internal improvements to ``NamedArg`` and ``ArgLists`` (`#389 <https://github.com/fmtlib/fmt/pull/389>`_ and `#390 <https://github.com/fmtlib/fmt/pull/390>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_.
* Fixed crash due to bug in ``FormatBuf`` (`#493 <https://github.com/fmtlib/fmt/pull/493>`_). Thanks `@effzeh <https://github.com/effzeh>`_. See also `#480 <https://github.com/fmtlib/fmt/issues/480>`_ and `#491 <https://github.com/fmtlib/fmt/issues/491>`_.
* Fixed handling of wide strings in ``fmt::StringWriter``.
* Improved compiler error messages (`#357 <https://github.com/fmtlib/fmt/issues/357>`_).
* Fixed various warnings and issues with various compilers (`#494 <https://github.com/fmtlib/fmt/pull/494>`_, `#499 <https://github.com/fmtlib/fmt/pull/499>`_, `#483 <https://github.com/fmtlib/fmt/pull/483>`_, `#519 <https://github.com/fmtlib/fmt/pull/519>`_, `#485 <https://github.com/fmtlib/fmt/pull/485>`_, `#482 <https://github.com/fmtlib/fmt/pull/482>`_, `#475 <https://github.com/fmtlib/fmt/pull/475>`_, `#473 <https://github.com/fmtlib/fmt/pull/473>`_ and `#414 <https://github.com/fmtlib/fmt/pull/414>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_, `@zhaohuaxishi <https://github.com/zhaohuaxishi>`_, `@pkestene (Pierre Kestener) <https://github.com/pkestene>`_, `@dschmidt (Dominik Schmidt) <https://github.com/dschmidt>`_ and `@0x414c (Alexey Gorishny) <https://github.com/0x414c>`_ .
* Improved CMake: targets are now namespaced (`#511 <https://github.com/fmtlib/fmt/pull/511>`_ and `#513 <https://github.com/fmtlib/fmt/pull/513>`_), supported header-only ``printf.h`` (`#354 <https://github.com/fmtlib/fmt/pull/354>`_), fixed issue with minimal supported library subset (`#418 <https://github.com/fmtlib/fmt/issues/418>`_, `#419 <https://github.com/fmtlib/fmt/pull/419>`_ and `#420 <https://github.com/fmtlib/fmt/pull/420>`_). Thanks `@bjoernthiel (Bjoern Thiel) <https://github.com/bjoernthiel>`_,
`@niosHD (Mario Werner) <https://github.com/niosHD>`_, `@LogicalKnight (Sean LK) <https://github.com/LogicalKnight>`_ and `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
* Improved documentation. Thanks to `@pwm1234 (Phil) <https://github.com/pwm1234>`_ for `#393 <https://github.com/fmtlib/fmt/pull/393>`_.
3.0.2 - 2017-06-14
------------------
* Added ``FMT_VERSION`` macro (`#411 <https://github.com/fmtlib/fmt/issues/411>`_).
* Used ``FMT_NULL`` instead of literal ``0`` (`#409 <https://github.com/fmtlib/fmt/pull/409>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
* Added extern templates for ``format_float`` (`#413 <https://github.com/fmtlib/fmt/issues/413>`_).
* Fixed implicit conversion issue (`#507 <https://github.com/fmtlib/fmt/issues/507>`_).
* Fixed signbit detection (`#423 <https://github.com/fmtlib/fmt/issues/423>`_).
* Fixed naming collision (`#425 <https://github.com/fmtlib/fmt/issues/425>`_).
* Fixed missing intrinsic for C++/CLI (`#457 <https://github.com/fmtlib/fmt/pull/457>`_). Thanks `@calumr (Calum Robinson) <https://github.com/calumr>`_
* Fixed Android detection (`#458 <https://github.com/fmtlib/fmt/pull/458>`_). Thanks `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_.
* Use lean ``windows.h`` if not in header-only mode (`#503 <https://github.com/fmtlib/fmt/pull/503>`_). Thanks `@Quentin01 (Quentin Buathier) <https://github.com/Quentin01>`_.
* Fixed issue with CMake exporting C++11 flag (`#445 <https://github.com/fmtlib/fmt/pull/455>`_). Thanks `@EricWF (Eric) <https://github.com/EricWF>`_.
* Fixed issue with nvcc and MSVC compiler bug and MinGW (`#505 <https://github.com/fmtlib/fmt/issues/505>`_).
* Fixed DLL issues (`#469 <https://github.com/fmtlib/fmt/pull/469>`_ and `#502 <https://github.com/fmtlib/fmt/pull/502>`_). Thanks `@richardeakin (Richard Eakin) <https://github.com/richardeakin>`_ and `@AndreasSchoenle (Andreas Schönle) <https://github.com/AndreasSchoenle>`_.
* Fixed test compilation under FreeBSD (`#433 <https://github.com/fmtlib/fmt/issues/433>`_).
* Fixed various warnings (`#403 <https://github.com/fmtlib/fmt/pull/403>`_, `#410 <https://github.com/fmtlib/fmt/pull/410>`_ and `#510 <https://github.com/fmtlib/fmt/pull/510>`_). Thanks `@Lecetem <https://github.com/Lectem>`_, `@chenhayat (Chen Hayat) <https://github.com/chenhayat>`_ and `@trozen <https://github.com/trozen>`_.
* Removed redundant include (`#479 <https://github.com/fmtlib/fmt/issues/479>`_).
* Fixed documentation issues.
3.0.1 - 2016-11-01
------------------
* Fixed handling of thousands seperator (`#353 <https://github.com/fmtlib/fmt/issues/353>`_)
* Fixed handling of ``unsigned char`` strings (`#373 <https://github.com/fmtlib/fmt/issues/373>`_)
* Corrected buffer growth when formatting time (`#367 <https://github.com/fmtlib/fmt/issues/367>`_)
* Removed warnings under MSVC and clang (`#318 <https://github.com/fmtlib/fmt/issues/318>`_, `#250 <https://github.com/fmtlib/fmt/issues/250>`_, also merged `#385 <https://github.com/fmtlib/fmt/pull/385>`_ and `#361 <https://github.com/fmtlib/fmt/pull/361>`_). Thanks `@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_ and `@nmoehrle (Nils Moehrle) <https://github.com/nmoehrle>`_.
* Fixed compilation issues under Android (`#327 <https://github.com/fmtlib/fmt/pull/327>`_, `#345 <https://github.com/fmtlib/fmt/issues/345>`_ and `#381 <https://github.com/fmtlib/fmt/pull/381>`_), FreeBSD (`#358 <https://github.com/fmtlib/fmt/pull/358>`_), Cygwin (`#388 <https://github.com/fmtlib/fmt/issues/388>`_), MinGW (`#355 <https://github.com/fmtlib/fmt/issues/355>`_) as well as other issues (`#350 <https://github.com/fmtlib/fmt/issues/350>`_, `#366 <https://github.com/fmtlib/fmt/issues/355>`_, `#348 <https://github.com/fmtlib/fmt/pull/348>`_, `#402 <https://github.com/fmtlib/fmt/pull/402>`_, `#405 <https://github.com/fmtlib/fmt/pull/405>`_). Thanks to `@dpantele (Dmitry) <https://github.com/dpantele>`_, `@hghwng (Hugh Wang) <https://github.com/hghwng>`_, `@arvedarved (Tilman Keskinöz) <https://github.com/arvedarved>`_, `@LogicalKnight (Sean) <https://github.com/LogicalKnight>`_ and `@JanHellwig (Jan Hellwig) <https://github.com/janhellwig>`_.
* Fixed some documentation issues and extended specification (`#320 <https://github.com/fmtlib/fmt/issues/320>`_, `#333 <https://github.com/fmtlib/fmt/pull/333>`_, `#347 <https://github.com/fmtlib/fmt/issues/347>`_, `#362 <https://github.com/fmtlib/fmt/pull/362>`_). Thanks to `@smellman (Taro Matsuzawa aka. btm) <https://github.com/smellman>`_.
3.0.0 - 2016-05-07
------------------
+28 -5
View File
@@ -20,9 +20,11 @@ alternative to IOStreams.
Features
--------
* Two APIs: faster concatenation-based write API and slower (but still
very fast) replacement-based format API with positional arguments for
localization.
* Two APIs: faster concatenation-based `write API
<http://fmtlib.net/latest/api.html#write-api>`_ and slower,
but still very fast, replacement-based `format API
<http://fmtlib.net/latest/api.html#format-api>`_ with positional arguments
for localization.
* Write API similar to the one used by IOStreams but stateless allowing
faster implementation.
* Format API with `format string syntax
@@ -35,10 +37,10 @@ Features
* Support for user-defined types.
* High speed: performance of the format API is close to that of
glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_
and better than performance of IOStreams. See `Speed tests`_ and
and better than the performance of IOStreams. See `Speed tests`_ and
`Fast integer to string conversion in C++
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
* Small code size both in terms of source code (format consists of a single
* Small code size both in terms of source code (the core library consists of a single
header file and a single source file) and compiled code.
See `Compile time and code bloat`_.
* Reliability: the library has an extensive set of `unit tests
@@ -89,6 +91,8 @@ An object of any user-defined type for which there is an overloaded
.. code:: c++
#include "fmt/ostream.h"
class Date {
int year_, month_, day_;
public:
@@ -132,6 +136,12 @@ Projects using this library
* `AMPL/MP <https://github.com/ampl/mp>`_:
An open-source library for mathematical programming
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle
* `Drake <http://drake.mit.edu/>`_: A planning, control, and analysis toolbox for nonlinear dynamical systems (MIT)
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus (Lyft)
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
Player vs Player Gaming Network with tweaks
@@ -139,6 +149,8 @@ Projects using this library
* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
@@ -158,6 +170,12 @@ Projects using this library
* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
Business intelligence software
* `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store that can handle
1 million transactions per second on a single server
* `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ framework for
high-performance server applications on modern hardware
* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
* `Stellar <https://www.stellar.org/>`_: Financial platform
@@ -390,6 +408,11 @@ It only applies if you distribute the documentation of fmt.
Acknowledgments
---------------
The fmt library is maintained by Victor Zverovich (`vitaut <https://github.com/vitaut>`_)
and Jonathan Müller (`foonathan <https://github.com/foonathan>`_) with contributions from many
other people. See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and `Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. Let us know if your contribution
is not listed or mentioned incorrectly and we'll make it right.
The benchmark section of this readme file and the performance tests are taken
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
written by Chris Foster. Boost Format library is acknowledged transitively
-2
View File
@@ -1,2 +0,0 @@
#include "../fmt/format.h"
#warning Including cppformat/format.h is deprecated. Include fmt/format.h instead.
-2
View File
@@ -1,2 +0,0 @@
#include "../fmt/posix.h"
#warning Including cppformat/posix.h is deprecated. Include fmt/posix.h instead.
+4 -2
View File
@@ -5,6 +5,8 @@ if (NOT DOXYGEN)
endif ()
add_custom_target(doc
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.py ${FMT_VERSION})
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.py ${FMT_VERSION}
SOURCES build.py conf.py _templates/layout.html)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ DESTINATION share/doc/fmt)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
DESTINATION share/doc/fmt OPTIONAL)
+28
View File
@@ -0,0 +1,28 @@
/* -- breathe specific styles ----------------------------------------------- */
/* So enum value descriptions are displayed inline to the item */
.breatheenumvalues li tt + p {
display: inline;
}
/* So parameter descriptions are displayed inline to the item */
.breatheparameterlist li tt + p {
display: inline;
}
.container .breathe-sectiondef {
width: inherit;
}
.github-btn {
border: 0;
overflow: hidden;
}
.jumbotron {
background-size: 100% 4px;
background-repeat: repeat-y;
color: white;
text-align: center;
}
+31 -20
View File
@@ -8,8 +8,9 @@
{# Google Analytics #}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -17,9 +18,11 @@
{% endblock %}
{%- macro searchform(classes, button) %}
<form class="{{classes}}" role="search" action="{{ pathto('search') }}" method="get">
<form class="{{classes}}" role="search" action="{{ pathto('search') }}"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" {{ 'placeholder="Search"' if not button }} >
<input type="text" name="q" class="form-control"
{{ 'placeholder="Search"' if not button }} >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -36,7 +39,8 @@
<div class="navbar-content">
{# Brand and toggle get grouped for better mobile display #}
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -49,18 +53,19 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
{# TODO: update versions automatically #}
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">{{ version }} <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">{{ version }}
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
{% for v in versions.split(',') %}
<li><a href="http://fmtlib.net/{{v}}">{{v}}</a></li>
{% endfor %}
</ul>
</li>
{% for name in ['Contents', 'Usage', 'API', 'Syntax'] %}
{% if pagename == name.lower() %}
<li class="active"><a href="{{name.lower()}}.html">{{name}} <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="{{name.lower()}}.html">{{name}}
<span class="sr-only">(current)</span></a></li>
{%else%}
<li><a href="{{name.lower()}}.html">{{name}}</a></li>
{%endif%}
@@ -75,20 +80,25 @@
</div> {# /.tb-container #}
</nav>
{% if pagename == "index" %}
{% set download_url = 'https://github.com/fmtlib/fmt/releases/download' %}
<div class="jumbotron">
<div class="tb-container">
<h1>{fmt}</h1>
<p class="lead">Small, safe and fast formatting library</p>
<div class="btn-group" role="group">
{% set name = 'fmt' if version.split('.')[0]|int >= 3 else 'cppformat' %}
<a class="btn btn-success"
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
href="{{download_url}}/{{version}}/{{name}}-{{version}}.zip">
<span class="glyphicon glyphicon-download"></span> Download
</a>
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<button type="button" class="btn btn-success dropdown-toggle"
data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.0.0/cppformat-1.0.0.zip">Version 1.0.0</a></li>
{% for v in versions.split(',') %}
{% set name = 'fmt' if v.split('.')[0]|int >= 3 else 'cppformat' %}
<li><a href="{{download_url}}/{{v}}/{{name}}-{{v}}.zip">Version {{v}}
</a></li>
{% endfor %}
</ul>
</div>
</div>
@@ -105,14 +115,15 @@
{% block content %}
<div class="tb-container">
<div class="row">
{# TODO: integrate sidebar
{# Sidebar is currently disabled.
<div class="bs-sidebar">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}"
alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
+78 -12
View File
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
Format API
==========
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
The following functions defined in ``fmt/format.h`` use :ref:`format string
syntax <syntax>` similar to the one used by Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
They take *format_str* and *args* as arguments.
@@ -22,6 +22,11 @@ arguments in the resulting string.
*args* is an argument list representing arbitrary arguments.
The `performance of the format API
<https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests>`_ is close
to that of glibc's ``printf`` and better than the performance of IOStreams.
For even better speed use the `write API`_.
.. _format:
.. doxygenfunction:: format(CStringRef, ArgList)
@@ -40,8 +45,9 @@ arguments in the resulting string.
Date and time formatting
------------------------
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
date and time formatting::
The library supports `strftime
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
formatting::
#include "fmt/time.h"
@@ -52,6 +58,36 @@ date and time formatting::
The format string syntax is described in the documentation of
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
Formatting user-defined types
-----------------------------
A custom ``format_arg`` function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in :file:`fmt/time.h`. The following example
shows how to implement custom formatting for a user-defined structure.
::
struct MyStruct { double a, b; };
void format_arg(fmt::BasicFormatter<char> &f,
const char *&format_str, const MyStruct &s) {
f.writer().write("[MyStruct: a={:.1f}, b={:.2f}]", s.a, s.b);
}
MyStruct m = { 1, 2 };
std::string s = fmt::format("m={}", n);
// s == "m=[MyStruct: a=1.0, b=2.00]"
Note in the example above the ``format_arg`` function ignores the contents of
``format_str`` so the type will always be formatted as specified. See
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
the ``format_str`` argument to customize the formatted output.
This section shows how to define a custom format function for a user-defined
type. The next section describes how to get ``fmt`` to use a conventional stream
output ``operator<<`` when one is defined for a user-defined type.
``std::ostream`` support
------------------------
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
Date(int year, int month, int day): year_(year), month_(month), day_(day) {}
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
@@ -75,8 +111,6 @@ formatting of user-defined types that have overloaded ``operator<<``::
.. doxygenfunction:: print(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
Argument formatters
-------------------
@@ -86,7 +120,7 @@ custom argument formatter class::
// A custom argument formatter that formats negative integers as unsigned
// with the ``x`` format specifier.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
@@ -120,22 +154,43 @@ custom argument formatter class::
.. doxygenclass:: fmt::ArgFormatter
:members:
Printf formatting functions
---------------------------
Printf formatting
-----------------
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
The following functions use `printf format string syntax
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
a POSIX extension for positional arguments.
the POSIX extension for positional arguments. Unlike their standard
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
argument type doesn't match its format specification.
.. doxygenfunction:: printf(CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: sprintf(CStringRef, ArgList)
.. doxygenclass:: fmt::PrintfFormatter
:members:
.. doxygenclass:: fmt::BasicPrintfArgFormatter
:members:
.. doxygenclass:: fmt::PrintfArgFormatter
:members:
Write API
=========
The write API provides classes for writing formatted data into character
streams. It is usually faster than the `format API`_ but, as IOStreams,
may result in larger compiled code size. The main writer class is
`~fmt::BasicMemoryWriter` which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing `~fmt::BasicWriter`.
.. doxygenclass:: fmt::BasicWriter
:members:
@@ -145,6 +200,12 @@ Write API
.. doxygenclass:: fmt::BasicArrayWriter
:members:
.. doxygenclass:: fmt::BasicStringWriter
:members:
.. doxygenclass:: fmt::BasicContainerWriter
:members:
.. doxygenfunction:: bin(int)
.. doxygenfunction:: oct(int)
@@ -169,6 +230,8 @@ Utilities
.. doxygenclass:: fmt::ArgList
:members:
.. doxygenfunction:: fmt::to_string(const T&)
.. doxygenclass:: fmt::BasicStringRef
:members:
@@ -185,6 +248,8 @@ System errors
.. doxygenclass:: fmt::SystemError
:members:
.. doxygenfunction:: fmt::format_system_error
.. doxygenclass:: fmt::WindowsError
:members:
@@ -202,7 +267,8 @@ A custom allocator class can be specified as a template argument to
It is also possible to write a formatting function that uses a custom
allocator::
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator> CustomString;
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator>
CustomString;
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
fmt::ArgList args) {
+2 -1
View File
@@ -90,7 +90,8 @@
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
</script>
{%- for scriptfile in script_files %}
+46 -28
View File
@@ -8,30 +8,35 @@ from distutils.version import LooseVersion
def pip_install(package, commit=None, **kwargs):
"Install package using pip."
min_version = kwargs.get('min_version')
if min_version:
from pkg_resources import get_distribution, DistributionNotFound
try:
installed_version = get_distribution(os.path.basename(package)).version
if LooseVersion(installed_version) >= min_version:
print('{} {} already installed'.format(package, min_version))
return
except DistributionNotFound:
pass
if commit:
check_version = kwargs.get('check_version', '')
#output = check_output(['pip', 'show', package.split('/')[1]])
#if check_version in output:
# print('{} already installed'.format(package))
# return
package = 'git+git://github.com/{0}.git@{1}'.format(package, commit)
print('Installing {}'.format(package))
check_call(['pip', 'install', '--upgrade', package])
package = 'git+https://github.com/{0}.git@{1}'.format(package, commit)
print('Installing {0}'.format(package))
check_call(['pip', 'install', package])
def build_docs(version='dev'):
def create_build_env(dirname='virtualenv'):
# Create virtualenv.
doc_dir = os.path.dirname(os.path.realpath(__file__))
virtualenv_dir = 'virtualenv'
check_call(['virtualenv', virtualenv_dir])
if not os.path.exists(dirname):
check_call(['virtualenv', dirname])
import sysconfig
scripts_dir = os.path.basename(sysconfig.get_path('scripts'))
activate_this_file = os.path.join(virtualenv_dir, scripts_dir,
'activate_this.py')
activate_this_file = os.path.join(dirname, scripts_dir, 'activate_this.py')
with open(activate_this_file) as f:
exec(f.read(), dict(__file__=activate_this_file))
# Import get_distribution after activating virtualenv to get info about
# the correct packages.
from pkg_resources import get_distribution, DistributionNotFound
# Upgrade pip because installation of sphinx with pip 1.1 available on Travis
# is broken (see #207) and it doesn't support the show command.
from pkg_resources import get_distribution, DistributionNotFound
pip_version = get_distribution('pip').version
if LooseVersion(pip_version) < LooseVersion('1.5.4'):
print("Updating pip")
@@ -46,27 +51,35 @@ def build_docs(version='dev'):
except DistributionNotFound:
pass
# Install Sphinx and Breathe.
pip_install('fmtlib/sphinx',
'12dde8afdb0a7bb5576e2656692c3478c69d8cc3',
check_version='1.4a0.dev-20151013')
pip_install('sphinx-doc/sphinx', '12b83372ac9316e8cbe86e7fed889296a4cc29ee',
min_version='1.4.1.dev20160531')
pip_install('michaeljones/breathe',
'1c9d7f80378a92cffa755084823a78bb38ee4acc')
'6b1c5bb7a1866f15fc328b8716258354b10c1daa',
min_version='4.2.0')
def build_docs(version='dev', **kwargs):
doc_dir = kwargs.get('doc_dir', os.path.dirname(os.path.realpath(__file__)))
work_dir = kwargs.get('work_dir', '.')
include_dir = kwargs.get('include_dir',
os.path.join(os.path.dirname(doc_dir), 'fmt'))
# Build docs.
cmd = ['doxygen', '-']
p = Popen(cmd, stdin=PIPE)
doxyxml_dir = os.path.join(work_dir, 'doxyxml')
p.communicate(input=r'''
PROJECT_NAME = fmt
GENERATE_LATEX = NO
GENERATE_MAN = NO
GENERATE_RTF = NO
CASE_SENSE_NAMES = NO
INPUT = {0}/format.h {0}/ostream.h
INPUT = {0}/container.h {0}/format.h {0}/ostream.h \
{0}/printf.h {0}/string.h
QUIET = YES
JAVADOC_AUTOBRIEF = YES
AUTOLINK_SUPPORT = NO
GENERATE_HTML = NO
GENERATE_XML = YES
XML_OUTPUT = doxyxml
XML_OUTPUT = {1}
ALIASES = "rst=\verbatim embed:rst"
ALIASES += "endrst=\endverbatim"
MACRO_EXPANSION = YES
@@ -76,24 +89,29 @@ def build_docs(version='dev'):
FMT_USE_USER_DEFINED_LITERALS=1 \
FMT_API=
EXCLUDE_SYMBOLS = fmt::internal::* StringValue write_str
'''.format(os.path.join(os.path.dirname(doc_dir), 'fmt')).encode('UTF-8'))
'''.format(include_dir, doxyxml_dir).encode('UTF-8'))
if p.returncode != 0:
raise CalledProcessError(p.returncode, cmd)
html_dir = os.path.join(work_dir, 'html')
versions = ['3.0.0', '2.0.0', '1.1.0']
check_call(['sphinx-build',
'-Dbreathe_projects.format=' + os.path.join(os.getcwd(), 'doxyxml'),
'-Dversion=' + version, '-Drelease=' + version, '-Aversion=' + version,
'-b', 'html', doc_dir, 'html'])
'-Dbreathe_projects.format=' + os.path.abspath(doxyxml_dir),
'-Dversion=' + version, '-Drelease=' + version,
'-Aversion=' + version, '-Aversions=' + ','.join(versions),
'-b', 'html', doc_dir, html_dir])
try:
check_call(['lessc', '--clean-css',
'--include-path=' + os.path.join(doc_dir, 'bootstrap'),
os.path.join(doc_dir, 'fmt.less'),
'html/_static/fmt.css'])
os.path.join(html_dir, '_static', 'fmt.css')])
except OSError as e:
if e.errno != errno.ENOENT:
raise
print('lessc not found; make sure that Less (http://lesscss.org/) is installed')
print('lessc not found; make sure that Less (http://lesscss.org/) ' +
'is installed')
sys.exit(1)
return 'html'
return html_dir
if __name__ == '__main__':
create_build_env()
build_docs(sys.argv[1])
+3 -4
View File
@@ -228,8 +228,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'format', u'format Documentation',
[u'Victor Zverovich'], 1)
('index', 'fmt', u'fmt documentation', [u'Victor Zverovich'], 1)
]
# If true, show URL addresses after external links.
@@ -242,8 +241,8 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'format', u'format Documentation',
u'Victor Zverovich', 'format', 'One line description of project.',
('index', 'fmt', u'fmt documentation',
u'Victor Zverovich', 'fmt', 'One line description of project.',
'Miscellaneous'),
]
+78 -12
View File
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
Format API
==========
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
The following functions defined in ``fmt/format.h`` use :ref:`format string
syntax <syntax>` similar to the one used by Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
They take *format_str* and *args* as arguments.
@@ -22,6 +22,11 @@ arguments in the resulting string.
*args* is an argument list representing arbitrary arguments.
The `performance of the format API
<https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests>`_ is close
to that of glibc's ``printf`` and better than the performance of IOStreams.
For even better speed use the `write API`_.
.. _format:
.. doxygenfunction:: format(CStringRef, ArgList)
@@ -40,8 +45,9 @@ arguments in the resulting string.
Date and time formatting
------------------------
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
date and time formatting::
The library supports `strftime
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
formatting::
#include "fmt/time.h"
@@ -52,6 +58,36 @@ date and time formatting::
The format string syntax is described in the documentation of
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
Formatting user-defined types
-----------------------------
A custom ``format_arg`` function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in :file:`fmt/time.h`. The following example
shows how to implement custom formatting for a user-defined structure.
::
struct MyStruct { double a, b; };
void format_arg(fmt::BasicFormatter<char> &f,
const char *&format_str, const MyStruct &s) {
f.writer().write("[MyStruct: a={:.1f}, b={:.2f}]", s.a, s.b);
}
MyStruct m = { 1, 2 };
std::string s = fmt::format("m={}", n);
// s == "m=[MyStruct: a=1.0, b=2.00]"
Note in the example above the ``format_arg`` function ignores the contents of
``format_str`` so the type will always be formatted as specified. See
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
the ``format_str`` argument to customize the formatted output.
This section shows how to define a custom format function for a user-defined
type. The next section describes how to get ``fmt`` to use a conventional stream
output ``operator<<`` when one is defined for a user-defined type.
``std::ostream`` support
------------------------
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
Date(int year, int month, int day): year_(year), month_(month), day_(day) {}
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
@@ -75,8 +111,6 @@ formatting of user-defined types that have overloaded ``operator<<``::
.. doxygenfunction:: print(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
Argument formatters
-------------------
@@ -86,7 +120,7 @@ custom argument formatter class::
// A custom argument formatter that formats negative integers as unsigned
// with the ``x`` format specifier.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
@@ -120,22 +154,43 @@ custom argument formatter class::
.. doxygenclass:: fmt::ArgFormatter
:members:
Printf formatting functions
---------------------------
Printf formatting
-----------------
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
The following functions use `printf format string syntax
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
a POSIX extension for positional arguments.
the POSIX extension for positional arguments. Unlike their standard
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
argument type doesn't match its format specification.
.. doxygenfunction:: printf(CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: sprintf(CStringRef, ArgList)
.. doxygenclass:: fmt::PrintfFormatter
:members:
.. doxygenclass:: fmt::BasicPrintfArgFormatter
:members:
.. doxygenclass:: fmt::PrintfArgFormatter
:members:
Write API
=========
The write API provides classes for writing formatted data into character
streams. It is usually faster than the `format API`_ but, as IOStreams,
may result in larger compiled code size. The main writer class is
`~fmt::BasicMemoryWriter` which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing `~fmt::BasicWriter`.
.. doxygenclass:: fmt::BasicWriter
:members:
@@ -145,6 +200,12 @@ Write API
.. doxygenclass:: fmt::BasicArrayWriter
:members:
.. doxygenclass:: fmt::BasicStringWriter
:members:
.. doxygenclass:: fmt::BasicContainerWriter
:members:
.. doxygenfunction:: bin(int)
.. doxygenfunction:: oct(int)
@@ -169,6 +230,8 @@ Utilities
.. doxygenclass:: fmt::ArgList
:members:
.. doxygenfunction:: fmt::to_string(const T&)
.. doxygenclass:: fmt::BasicStringRef
:members:
@@ -185,6 +248,8 @@ System errors
.. doxygenclass:: fmt::SystemError
:members:
.. doxygenfunction:: fmt::format_system_error
.. doxygenclass:: fmt::WindowsError
:members:
@@ -202,7 +267,8 @@ A custom allocator class can be specified as a template argument to
It is also possible to write a formatting function that uses a custom
allocator::
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator> CustomString;
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator>
CustomString;
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
fmt::ArgList args) {
+32 -29
View File
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
Thanks for creating this library. Its been a hole in C++ for a long time.
Ive used both boost::format and loki::SPrintf, and neither felt like the
right answer. This does.
Thanks for creating this library. Its been a hole in C++ for a long
time. Ive used both boost::format and loki::SPrintf, and neither felt
like the right answer. This does.
</div>
</div>
@@ -24,8 +24,8 @@ Format API
The replacement-based Format API provides a safe alternative to ``printf``,
``sprintf`` and friends with comparable or `better performance
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
The `format string syntax <syntax.html>`_ is similar to the one used by
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
in Python:
.. code:: c++
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
Write API
---------
The concatenation-based Write API (experimental) provides a
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
The concatenation-based Write API (experimental) provides a `fast
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
stateless alternative to IOStreams:
.. code:: c++
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
Safety
------
The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code
The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code
.. code:: c++
@@ -138,19 +139,21 @@ formatted into a narrow string. You can use a wide format string instead:
fmt::format(L"Cyrillic letter {}", L'\x42e');
For comparison, writing a wide character to ``std::ostream`` results in
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю' which
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
needed.
.. _portability:
Portability
-----------
The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:
The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:
* 64-bit (amd64) GNU/Linux with GCC 4.4.3, `4.6.3 <https://travis-ci.org/fmtlib/fmt>`_,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
`4.6.3 <https://travis-ci.org/fmtlib/fmt>`_, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2
* 32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3
@@ -161,21 +164,21 @@ compilers where it has been tested and known to work:
* 32-bit Windows with Visual C++ 2010
Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:
Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
``fmt::format`` and ``fmt::arg``.
The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives ``inf`` while the output
of ``printf`` is platform-dependent in this case. For example,
The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives ``inf`` while the
output of ``printf`` is platform-dependent in this case. For example,
.. code::
@@ -188,10 +191,10 @@ always prints ``inf``.
Ease of Use
-----------
fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD `license
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
in open-source and commercial projects.
fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
using the library both in open-source and commercial projects.
.. raw:: html
+7 -9
View File
@@ -49,12 +49,10 @@ mini-language" or interpretation of the *format_spec*.
Most built-in types support a common formatting mini-language, which is
described in the next section.
A *format_spec* field can also include nested replacement fields within it.
These nested replacement fields can contain only an argument index;
format specifications are not allowed. Formatting is performed as if the
replacement fields within the format_spec are substituted before the
*format_spec* string is interpreted. This allows the formatting of a value
to be dynamically specified.
A *format_spec* field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
sign: "+" | "-" | " "
width: `integer` | "{" `arg_id` "}"
precision: `integer` | "{" `arg_id` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "n" | "o" | "x" | "X"
The *fill* character can be any character other than '{' or '}'. The presence
of a fill character is signaled by the character following it, which must be
@@ -234,7 +232,7 @@ The available presentation types for floating-point values are:
+=========+==========================================================+
| ``'a'`` | Hexadecimal floating point format. Prints the number in |
| | base 16 with prefix ``"0x"`` and lower-case letters for |
| | digits above 9. Uses 'p' to indicate the exponent. |
| | digits above 9. Uses ``'p'`` to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'A'`` | Same as ``'a'`` except it uses upper-case letters for |
| | the prefix, digits above 9 and to indicate the exponent. |
+23 -2
View File
@@ -54,6 +54,23 @@ To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to
__ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries
Header-only usage with CMake
============================
In order to add ``fmtlib`` into an existing ``CMakeLists.txt`` file, you can add the ``fmt`` library directory into your main project, which will enable the ``fmt`` library::
add_subdirectory(fmt)
If you have a project called ``foo`` that you would like to link against the fmt library in a header-only fashion, you can enable with with::
target_link_libraries(foo PRIVATE fmt::fmt-header-only)
And then to ensure that the ``fmt`` library does not always get built, you can modify the call to ``add_subdirectory`` to read ::
add_subdirectory(fmt EXCLUDE_FROM_ALL)
This will ensure that the ``fmt`` library is exluded from calls to ``make``, ``make all``, or ``cmake --build .``.
Building the documentation
==========================
@@ -62,7 +79,11 @@ system:
* `Python <https://www.python.org/>`_ with pip and virtualenv
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
* `Less <http://lesscss.org/>`_ with less-plugin-clean-css
* `Less <http://lesscss.org/>`_ with ``less-plugin-clean-css``.
Ubuntu doesn't package the ``clean-css`` plugin so you should use ``npm``
instead of ``apt`` to install both ``less`` and the plugin::
sudo npm install -g less less-plugin-clean-css.
First generate makefiles or project files using CMake as described in
the previous section. Then compile the ``doc`` target/project, for example::
@@ -87,4 +108,4 @@ Homebrew
fmt can be installed on OS X using `Homebrew <http://brew.sh/>`_::
brew install cppformat
brew install fmt
@@ -47,8 +47,10 @@
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
@@ -59,7 +61,9 @@
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
+405 -132
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>API Reference &mdash; fmt 3.0.0 documentation</title>
<title>API Reference &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -35,8 +36,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -50,7 +52,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -63,13 +66,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -82,7 +89,8 @@
<li class="active"><a href="api.html">API <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="api.html">API
<span class="sr-only">(current)</span></a></li>
@@ -92,9 +100,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -122,13 +132,16 @@ in namespace <code class="docutils literal"><span class="pre">fmt</span></code>
namespace is usually omitted in examples.</p>
<div class="section" id="format-api">
<h2>Format API<a class="headerlink" href="#format-api" title="Permalink to this headline"></a></h2>
<p>The following functions use <a class="reference internal" href="syntax.html#syntax"><span class="std std-ref">format string syntax</span></a> similar
to the one used by Python&#8217;s <a class="reference external" href="http://docs.python.org/3/library/stdtypes.html#str.format">str.format</a> function.
<p>The following functions defined in <code class="docutils literal"><span class="pre">fmt/format.h</span></code> use <a class="reference internal" href="syntax.html#syntax"><span class="std std-ref">format string
syntax</span></a> similar to the one used by Python&#8217;s <a class="reference external" href="http://docs.python.org/3/library/stdtypes.html#str.format">str.format</a> function.
They take <em>format_str</em> and <em>args</em> as arguments.</p>
<p><em>format_str</em> is a format string that contains literal text and replacement
fields surrounded by braces <code class="docutils literal"><span class="pre">{}</span></code>. The fields are replaced with formatted
arguments in the resulting string.</p>
<p><em>args</em> is an argument list representing arbitrary arguments.</p>
<p>The <a class="reference external" href="https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests">performance of the format API</a> is close
to that of glibc&#8217;s <code class="docutils literal"><span class="pre">printf</span></code> and better than the performance of IOStreams.
For even better speed use the <a class="reference internal" href="#write-api">write API</a>.</p>
<span class="target" id="format"></span><dl class="function">
<dt id="_CPPv2N3fmt6formatE10CStringRef7ArgList">
<span id="fmt::format__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a638f25c535b3bfa12dc1478b11885b6f"></span>std::string <code class="descclassname">fmt::</code><code class="descname">format</code><span class="sig-paren">(</span>CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
@@ -140,18 +153,10 @@ arguments in the resulting string.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">
<span class="target" id="formatformat_8h_1a8f568cdac4d075838347616fc4899417"></span>internal::UdlFormat&lt;char&gt; <code class="descclassname">fmt::literals::</code><code class="descname">operator&quot;&quot;_format</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>s</em>, std::size_t<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>C++11 literal equivalent of <a class="reference internal" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="fmt::format"><code class="xref cpp cpp-func docutils literal"><span class="pre">fmt::format()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">fmt</span><span class="o">::</span><span class="n">literals</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span> <span class="o">=</span> <span class="s">&quot;The answer is {}&quot;</span><span class="n">_format</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</pre></div>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">doxygenfunction: Cannot find function &#8220;operator&#8221;&#8220;_format&#8221; in doxygen xml output for project &#8220;format&#8221; from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
</div>
</p>
</dd></dl>
<span class="target" id="print"></span><dl class="function">
<dt id="_CPPv2N3fmt5printE10CStringRef7ArgList">
<span id="fmt::print__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a7cfad68e64995774f11072aaf5008e8a"></span>void <code class="descclassname">fmt::</code><code class="descname">print</code><span class="sig-paren">(</span>CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt5printE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
@@ -180,7 +185,8 @@ arguments in the resulting string.</p>
<dt id="_CPPv2N3fmt14BasicFormatterE">
<span id="fmt::BasicFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicFormatter</code><a class="headerlink" href="#_CPPv2N3fmt14BasicFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>This template formats data and writes the output to a writer. </p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::FormatterBase</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Types</p>
<dl class="type">
<dt id="_CPPv2N3fmt14BasicFormatter4CharE">
@@ -189,7 +195,7 @@ arguments in the resulting string.</p>
</dd></dl>
</div>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicFormatter14BasicFormatterERK7ArgListR11BasicWriterI4CharE">
@@ -217,8 +223,8 @@ appropriate lifetimes.</p>
<div class="section" id="date-and-time-formatting">
<h3>Date and time formatting<a class="headerlink" href="#date-and-time-formatting" title="Permalink to this headline"></a></h3>
<p>The library supports <a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>-like
date and time formatting:</p>
<p>The library supports <a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>-like date and time
formatting:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;fmt/time.h&quot;</span><span class="cp"></span>
<span class="n">std</span><span class="o">::</span><span class="kt">time_t</span> <span class="n">t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">time</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
@@ -229,6 +235,32 @@ date and time formatting:</p>
<p>The format string syntax is described in the documentation of
<a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>.</p>
</div>
<div class="section" id="formatting-user-defined-types">
<h3>Formatting user-defined types<a class="headerlink" href="#formatting-user-defined-types" title="Permalink to this headline"></a></h3>
<p>A custom <code class="docutils literal"><span class="pre">format_arg</span></code> function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in <code class="file docutils literal"><span class="pre">fmt/time.h</span></code>. The following example
shows how to implement custom formatting for a user-defined structure.</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">MyStruct</span> <span class="p">{</span> <span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span> <span class="p">};</span>
<span class="kt">void</span> <span class="nf">format_arg</span><span class="p">(</span><span class="n">fmt</span><span class="o">::</span><span class="n">BasicFormatter</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">f</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*&amp;</span><span class="n">format_str</span><span class="p">,</span> <span class="k">const</span> <span class="n">MyStruct</span> <span class="o">&amp;</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="n">f</span><span class="p">.</span><span class="n">writer</span><span class="p">().</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;[MyStruct: a={:.1f}, b={:.2f}]&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">MyStruct</span> <span class="n">m</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">s</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;m={}&quot;</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="c1">// s == &quot;m=[MyStruct: a=1.0, b=2.00]&quot;</span>
</pre></div>
</div>
<p>Note in the example above the <code class="docutils literal"><span class="pre">format_arg</span></code> function ignores the contents of
<code class="docutils literal"><span class="pre">format_str</span></code> so the type will always be formatted as specified. See
<code class="docutils literal"><span class="pre">format_arg</span></code> in <code class="file docutils literal"><span class="pre">fmt/time.h</span></code> for an advanced example of how to use
the <code class="docutils literal"><span class="pre">format_str</span></code> argument to customize the formatted output.</p>
<p>This section shows how to define a custom format function for a user-defined
type. The next section describes how to get <code class="docutils literal"><span class="pre">fmt</span></code> to use a conventional stream
output <code class="docutils literal"><span class="pre">operator&lt;&lt;</span></code> when one is defined for a user-defined type.</p>
</div>
<div class="section" id="std-ostream-support">
<h3><code class="docutils literal"><span class="pre">std::ostream</span></code> support<a class="headerlink" href="#std-ostream-support" title="Permalink to this headline"></a></h3>
<p>The header <code class="docutils literal"><span class="pre">fmt/ostream.h</span></code> provides <code class="docutils literal"><span class="pre">std::ostream</span></code> support including
@@ -238,7 +270,7 @@ formatting of user-defined types that have overloaded <code class="docutils lite
<span class="k">class</span> <span class="nc">Date</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">year_</span><span class="p">,</span> <span class="n">month_</span><span class="p">,</span> <span class="n">day_</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">Date</span><span class="p">(</span><span class="kt">int</span> <span class="n">year</span><span class="p">,</span> <span class="kt">int</span> <span class="n">month</span><span class="p">,</span> <span class="kt">int</span> <span class="n">day</span><span class="p">)</span> <span class="o">:</span> <span class="n">year_</span><span class="p">(</span><span class="n">year</span><span class="p">),</span> <span class="n">month_</span><span class="p">(</span><span class="n">month</span><span class="p">),</span> <span class="n">day_</span><span class="p">(</span><span class="n">day</span><span class="p">)</span> <span class="p">{}</span>
<span class="n">Date</span><span class="p">(</span><span class="kt">int</span> <span class="n">year</span><span class="p">,</span> <span class="kt">int</span> <span class="n">month</span><span class="p">,</span> <span class="kt">int</span> <span class="n">day</span><span class="p">)</span><span class="o">:</span> <span class="n">year_</span><span class="p">(</span><span class="n">year</span><span class="p">),</span> <span class="n">month_</span><span class="p">(</span><span class="n">month</span><span class="p">),</span> <span class="n">day_</span><span class="p">(</span><span class="n">day</span><span class="p">)</span> <span class="p">{}</span>
<span class="k">friend</span> <span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">Date</span> <span class="o">&amp;</span><span class="n">d</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">year_</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;-&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">month_</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;-&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">day_</span><span class="p">;</span>
@@ -260,17 +292,6 @@ formatting of user-defined types that have overloaded <code class="docutils lite
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">
<span id="fmt::fprintf__osR.CStringRef.ArgList"></span><span class="target" id="formatostream_8h_1adf9e00e4ddf5cad224a101333cfac9e8"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::ostream &amp;<em>os</em>, CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the stream <em>os</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fprintf</span><span class="p">(</span><span class="n">cerr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
</div>
<div class="section" id="argument-formatters">
<h3>Argument formatters<a class="headerlink" href="#argument-formatters" title="Permalink to this headline"></a></h3>
@@ -279,7 +300,7 @@ custom argument formatter class:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="c1">// A custom argument formatter that formats negative integers as unsigned</span>
<span class="c1">// with the ``x`` format specifier.</span>
<span class="k">class</span> <span class="nc">CustomArgFormatter</span> <span class="o">:</span>
<span class="k">public</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicArgFormatter</span><span class="o">&lt;</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="p">{</span>
<span class="k">public</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicArgFormatter</span><span class="o">&lt;</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">CustomArgFormatter</span><span class="p">(</span><span class="n">fmt</span><span class="o">::</span><span class="n">BasicFormatter</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">CustomArgFormatter</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">f</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">FormatSpec</span> <span class="o">&amp;</span><span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">)</span>
@@ -329,7 +350,7 @@ then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt1
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt10ArgVisitor9visit_intEi">
@@ -440,7 +461,7 @@ called.</p>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>&gt;</dt>
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em> = fmt::FormatSpec&gt;</dt>
<dt id="_CPPv2N3fmt17BasicArgFormatterE">
<span id="fmt::BasicArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p><p>An argument formatter based on the <a class="reference external" href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">curiously recurring template pattern</a>.</p>
@@ -455,11 +476,12 @@ will be called. If the subclass doesn&#8217;t contain a method with this signatu
then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt17BasicArgFormatterE" title="fmt::BasicArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicArgFormatter</span></code></a> or its superclass
will be called.</p>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::ArgFormatterBase&lt; Impl, Char, Spec &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char">
<span id="fmt::BasicArgFormatter::BasicArgFormatter__BasicFormatter:Char.Impl:R.FormatSpecR.CharCP"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1a207b17b258c5e16cf61ebfc9b13211d3"></span><code class="descname">BasicArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt14BasicFormatterE" title="fmt::BasicFormatter">BasicFormatter</a>&lt;Char, Impl&gt; &amp;<em>formatter</em>, FormatSpec &amp;<em>spec</em>, <em class="property">const</em> Char *<em>fmt</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char">
<span id="fmt::BasicArgFormatter::BasicArgFormatter__BasicFormatter:Char.Impl:R.SpecR.CharCP"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1a9fbfaaf573b6714ed03894326b0a5106"></span><code class="descname">BasicArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt14BasicFormatterE" title="fmt::BasicFormatter">BasicFormatter</a>&lt;Char, Impl&gt; &amp;<em>formatter</em>, Spec &amp;<em>spec</em>, <em class="property">const</em> Char *<em>fmt</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs an argument formatter object.
<em>formatter</em> is a reference to the main formatter object, <em>spec</em> contains
format specifier information for standard argument types, and <em>fmt</em> points
@@ -469,8 +491,8 @@ to the part of the format string being parsed for custom argument types.</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE">
<span id="fmt::BasicArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1ae0aab0f90c9c93e3513203fc84c2c4dc"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats argument of a custom (user-defined) type. </p>
<span id="fmt::BasicArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1acc822e8efaa99b664deaf38b08950b88"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of a custom (user-defined) type. </p>
</dd></dl>
</div>
@@ -482,7 +504,8 @@ to the part of the format string being parsed for custom argument types.</p>
<dt id="_CPPv2N3fmt12ArgFormatterE">
<span id="fmt::ArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">ArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt12ArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>The default argument formatter. </p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_arg_formatter"><span class="std std-ref">fmt::BasicArgFormatter&lt; ArgFormatter&lt; Char &gt;, Char, FormatSpec &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt12ArgFormatter12ArgFormatterER14BasicFormatterI4CharER10FormatSpecPK4Char">
@@ -494,13 +517,16 @@ to the part of the format string being parsed for custom argument types.</p>
</dd></dl>
</div>
<div class="section" id="printf-formatting-functions">
<h3>Printf formatting functions<a class="headerlink" href="#printf-formatting-functions" title="Permalink to this headline"></a></h3>
<p>The following functions use <a class="reference external" href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html">printf format string syntax</a> with
a POSIX extension for positional arguments.</p>
<div class="section" id="printf-formatting">
<h3>Printf formatting<a class="headerlink" href="#printf-formatting" title="Permalink to this headline"></a></h3>
<p>The header <code class="docutils literal"><span class="pre">fmt/printf.h</span></code> provides <code class="docutils literal"><span class="pre">printf</span></code>-like formatting functionality.
The following functions use <a class="reference external" href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html">printf format string syntax</a> with
the POSIX extension for positional arguments. Unlike their standard
counterparts, the <code class="docutils literal"><span class="pre">fmt</span></code> functions are type-safe and throw an exception if an
argument type doesn&#8217;t match its format specification.</p>
<dl class="function">
<dt id="_CPPv2N3fmt6printfE10CStringRef7ArgList">
<span id="fmt::printf__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1aa936ffccf89f4609cd9fce18825f0b14"></span>int <code class="descclassname">fmt::</code><code class="descname">printf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6printfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::printf__CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1aa936ffccf89f4609cd9fce18825f0b14"></span>int <code class="descclassname">fmt::</code><code class="descname">printf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6printfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to <code class="docutils literal"><span class="pre">stdout</span></code>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;Elapsed time: %.2f seconds&quot;</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">);</span>
@@ -511,7 +537,7 @@ a POSIX extension for positional arguments.</p>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">
<span id="fmt::fprintf__std::FILEP.CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1ae70c0a9615eef5e1e78450496d2a90e6"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::FILE *<em>f</em>, CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::fprintf__std::FILEP.CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1ae70c0a9615eef5e1e78450496d2a90e6"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::FILE *<em>f</em>, CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the file <em>f</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
@@ -520,9 +546,20 @@ a POSIX extension for positional arguments.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">
<span id="fmt::fprintf__osR.CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1adf9e00e4ddf5cad224a101333cfac9e8"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::ostream &amp;<em>os</em>, CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the stream <em>os</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fprintf</span><span class="p">(</span><span class="n">cerr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7sprintfE10CStringRef7ArgList">
<span id="fmt::sprintf__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a956d655d1291fb85203c58fadd4bba1a"></span>std::string <code class="descclassname">fmt::</code><code class="descname">sprintf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7sprintfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::sprintf__CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1a956d655d1291fb85203c58fadd4bba1a"></span>std::string <code class="descclassname">fmt::</code><code class="descname">sprintf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7sprintfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Formats arguments and returns the result as a string.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">sprintf</span><span class="p">(</span><span class="s">&quot;The answer is %d&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
@@ -531,10 +568,124 @@ a POSIX extension for positional arguments.</p>
</p>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_printf_formatter"></span><em class="property">template </em>&lt;typename <em>Char</em>, typename <em>ArgFormatter</em> = <a class="reference internal" href="#formatclassfmt_1_1_printf_arg_formatter"><span class="std std-ref">PrintfArgFormatter</span></a>&lt;Char&gt;&gt;</dt>
<dt id="_CPPv2N3fmt15PrintfFormatterE">
<span id="fmt::PrintfFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">PrintfFormatter</code><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>This template formats data and writes the output to a writer. </p>
<p>Inherits from fmt::internal::FormatterBase</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE">
<span id="fmt::PrintfFormatter::PrintfFormatter__ArgListCR.BasicWriter:Char:R"></span><span class="target" id="formatclassfmt_1_1_printf_formatter_1a9cb3cad9a8e4cd08445e9ff2338d40b0"></span><code class="descname">PrintfFormatter</code><span class="sig-paren">(</span><em class="property">const</em> <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> &amp;<em>al</em>, <a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <code class="docutils literal"><span class="pre">PrintfFormatter</span></code> object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE">
<span id="fmt::PrintfFormatter::format__BasicCStringRef:Char:"></span><span class="target" id="formatclassfmt_1_1_printf_formatter_1a295c50e11b9a77720c8078f287040e5c"></span>void <code class="descname">format</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt15BasicCStringRefE" title="fmt::BasicCStringRef">BasicCStringRef</a>&lt;Char&gt; <em>format_str</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE" title="Permalink to this definition"></a></dt>
<dd><p>Formats stored arguments and writes the output to the writer. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em>&gt;</dt>
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatterE">
<span id="fmt::BasicPrintfArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicPrintfArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p><p>A <code class="docutils literal"><span class="pre">printf</span></code> argument formatter based on the <a class="reference external" href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">curiously recurring template
pattern</a>.</p>
<p>To use <a class="reference internal" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="fmt::BasicPrintfArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicPrintfArgFormatter</span></code></a> define a subclass that implements some
or all of the visit methods with the same signatures as the methods in
<a class="reference internal" href="#_CPPv2N3fmt10ArgVisitorE" title="fmt::ArgVisitor"><code class="xref cpp cpp-any docutils literal"><span class="pre">ArgVisitor</span></code></a>, for example, <a class="reference internal" href="#_CPPv2N3fmt10ArgVisitor9visit_intEi" title="fmt::ArgVisitor::visit_int"><code class="xref cpp cpp-any docutils literal"><span class="pre">visit_int()</span></code></a>.
Pass the subclass as the <em>Impl</em> template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
<code class="docutils literal"><span class="pre">double</span></code> then the <a class="reference internal" href="#_CPPv2N3fmt10ArgVisitor12visit_doubleEd" title="fmt::ArgVisitor::visit_double"><code class="xref cpp cpp-any docutils literal"><span class="pre">visit_double()</span></code></a> method of a subclass
will be called. If the subclass doesn&#8217;t contain a method with this signature,
then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="fmt::BasicPrintfArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicPrintfArgFormatter</span></code></a> or its
superclass will be called.</p>
</p>
<p>Inherits from fmt::internal::ArgFormatterBase&lt; Impl, Char, Spec &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec">
<span id="fmt::BasicPrintfArgFormatter::BasicPrintfArgFormatter__BasicWriter:Char:R.SpecR"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a7027cf03f0a54f8d7e53563e948d9f54"></span><code class="descname">BasicPrintfArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em>, Spec &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs an argument formatter object.
<em>writer</em> is a reference to the output writer and <em>spec</em> contains format
specifier information for standard argument types.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb">
<span id="fmt::BasicPrintfArgFormatter::visit_bool__b"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a5a8896e3b7e60b678ad7ac1145d2d7db"></span>void <code class="descname">visit_bool</code><span class="sig-paren">(</span>bool <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of type <code class="docutils literal"><span class="pre">bool</span></code>. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi">
<span id="fmt::BasicPrintfArgFormatter::visit_char__i"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a6d6a9710fe756a8682efa6e83eea8146"></span>void <code class="descname">visit_char</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi" title="Permalink to this definition"></a></dt>
<dd><p>Formats a character. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc">
<span id="fmt::BasicPrintfArgFormatter::visit_cstring__cCP"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a202e5093c8d7ab388c05f58956e8f721"></span>void <code class="descname">visit_cstring</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc" title="Permalink to this definition"></a></dt>
<dd><p>Formats a null-terminated C string. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv">
<span id="fmt::BasicPrintfArgFormatter::visit_pointer__voidCP"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a4184ac39a994f38d4b4850393e413a1c"></span>void <code class="descname">visit_pointer</code><span class="sig-paren">(</span><em class="property">const</em> void *<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv" title="Permalink to this definition"></a></dt>
<dd><p>Formats a pointer. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE">
<span id="fmt::BasicPrintfArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a5ad1e99dfd69b88a6b7940c1bfc52d23"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of a custom (user-defined) type. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_printf_arg_formatter"></span><em class="property">template </em>&lt;<em class="property">typename</em> Char&gt;</dt>
<dt id="_CPPv2N3fmt18PrintfArgFormatterE">
<span id="fmt::PrintfArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">PrintfArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt18PrintfArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>The default printf argument formatter. </p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_printf_arg_formatter"><span class="std std-ref">fmt::BasicPrintfArgFormatter&lt; PrintfArgFormatter&lt; Char &gt;, Char, FormatSpec &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec">
<span id="fmt::PrintfArgFormatter::PrintfArgFormatter__BasicWriter:Char:R.FormatSpecR"></span><span class="target" id="formatclassfmt_1_1_printf_arg_formatter_1aa4b9526d3c614205d607f63918c33245"></span><code class="descname">PrintfArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em>, FormatSpec &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec" title="Permalink to this definition"></a></dt>
<dd><p>Constructs an argument formatter object. </p>
</dd></dl>
</div>
</dd></dl>
</div>
</div>
<div class="section" id="write-api">
<h2>Write API<a class="headerlink" href="#write-api" title="Permalink to this headline"></a></h2>
<p>The write API provides classes for writing formatted data into character
streams. It is usually faster than the <a class="reference internal" href="#format-api">format API</a> but, as IOStreams,
may result in larger compiled code size. The main writer class is
<a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicMemoryWriter</span></code></a> which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing <a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicWriter</span></code></a>.</p>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_writer"></span><em class="property">template </em>&lt;typename <em>Char</em>&gt;</dt>
@@ -564,37 +715,38 @@ such as <a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" ti
</tbody>
</table>
</p>
<div class="breathe-sectiondef container">
<p>Subclassed by <a class="reference internal" href="#formatclassfmt_1_1_basic_array_writer"><span class="std std-ref">fmt::BasicArrayWriter&lt; Char &gt;</span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_memory_writer"><span class="std std-ref">fmt::BasicMemoryWriter&lt; Char, Allocator &gt;</span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_string_writer"><span class="std std-ref">fmt::BasicStringWriter&lt; Char, Allocator &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriterD0Ev">
<span id="fmt::BasicWriter::~BasicWriter"></span>virtual <span class="target" id="formatclassfmt_1_1_basic_writer_1a25f6fc2e43d3bcfb3de9ac33afe6050d"></span><code class="descname">~BasicWriter</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11BasicWriterD0Ev" title="Permalink to this definition"></a></dt>
<span id="fmt::BasicWriter::~BasicWriter"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a25f6fc2e43d3bcfb3de9ac33afe6050d"></span><em class="property">virtual</em> <code class="descname">~BasicWriter</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11BasicWriterD0Ev" title="Permalink to this definition"></a></dt>
<dd><p><p>Destroys a <code class="docutils literal"><span class="pre">BasicWriter</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter4sizeEv">
<span id="fmt::BasicWriter::size"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a1b6721b4ba4d3fa18ac781a36616cc2a"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter4sizeEv">
<span id="fmt::BasicWriter::sizeC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a8d4534eea273ef4a3dd9078b995d3d15"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the total number of characters written. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter4dataEv">
<span id="fmt::BasicWriter::data"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a6f3f431fab4a937cd6844a5bda609391"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter4dataEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter4dataEv">
<span id="fmt::BasicWriter::dataC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a06ada257ca9ae580212d6fe0147fe2cc"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter4dataEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the output buffer content. </p>
<p>No terminating null character is appended. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter5c_strEv">
<span id="fmt::BasicWriter::c_str"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a8b68001f5c1c0ea851ddaef27dcbc691"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter5c_strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter5c_strEv">
<span id="fmt::BasicWriter::c_strC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1ab608044b16c838ed394cfe937e2ed8b9"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter5c_strEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the output buffer content with terminating null character appended. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter3strEv">
<span id="fmt::BasicWriter::str"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a91f06ced6e063ee77a99740e0e79faf6"></span>std::basic_string&lt;Char&gt; <code class="descname">str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter3strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter3strEv">
<span id="fmt::BasicWriter::strC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1aac8dbeddff3d4e268d17a4f9c16264f6"></span>std::basic_string&lt;Char&gt; <code class="descname">str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter3strEv" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns the content of the output buffer as an <code class="xref cpp cpp-any docutils literal"><span class="pre">std::string</span></code>.</p>
</p>
</dd></dl>
@@ -695,11 +847,12 @@ and the standard allocator:</p>
<p>The output can be converted to an <code class="docutils literal"><span class="pre">std::string</span></code> with <code class="docutils literal"><span class="pre">out.str()</span></code> or
accessed as a C string with <code class="docutils literal"><span class="pre">out.c_str()</span></code>.</p>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter">
<span id="fmt::BasicMemoryWriter::BasicMemoryWriter__BasicMemoryWriterRR"></span><span class="target" id="formatclassfmt_1_1_basic_memory_writer_1a245047763a93566d0a7c1f90e8901672"></span><code class="descname">BasicMemoryWriter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter">BasicMemoryWriter</a> &amp;&amp;<em>other</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="Permalink to this definition"></a></dt>
<span id="fmt::BasicMemoryWriter::BasicMemoryWriter__BasicMemoryWriterRR"></span><span class="target" id="formatclassfmt_1_1_basic_memory_writer_1a245047763a93566d0a7c1f90e8901672"></span><code class="descname">BasicMemoryWriter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="fmt::BasicMemoryWriter::BasicMemoryWriter">BasicMemoryWriter</a> &amp;&amp;<em>other</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicMemoryWriter</span></code></a> object moving the content
of the other object to it.</p>
</p>
@@ -746,7 +899,8 @@ into the array.</p>
</tbody>
</table>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt16BasicArrayWriter16BasicArrayWriterEP4CharNSt6size_tE">
@@ -769,27 +923,118 @@ size known at compile time.</p>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_string_writer"></span><em class="property">template </em>&lt;<em class="property">typename</em> Char, <em class="property">typename</em> Allocator = std::allocator&lt;Char&gt;&gt;</dt>
<dt id="_CPPv2N3fmt17BasicStringWriterE">
<span id="fmt::BasicStringWriter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicStringWriter</code><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriterE" title="Permalink to this definition"></a></dt>
<dd><p><p>This class template provides operations for formatting and writing data
into a character stream. The output is stored in a <code class="docutils literal"><span class="pre">std::basic_string</span></code>
that grows dynamically.</p>
<p>You can use one of the following typedefs for common character types
and the standard allocator:</p>
<table border="1" class="docutils">
<colgroup>
<col width="35%" />
<col width="65%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Type</th>
<th class="head">Definition</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>StringWriter</td>
<td>BasicStringWriter&lt;char&gt;</td>
</tr>
<tr class="row-odd"><td>WStringWriter</td>
<td>BasicStringWriter&lt;wchar_t&gt;</td>
</tr>
</tbody>
</table>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">StringWriter</span> <span class="n">out</span><span class="p">;</span>
<span class="n">out</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;The answer is &quot;</span> <span class="o">&lt;&lt;</span> <span class="mi">42</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span>
</pre></div>
</div>
<p>This will write the following output to the <code class="docutils literal"><span class="pre">out</span></code> object:</p>
<div class="highlight-none"><div class="highlight"><pre><span></span>The answer is 42
</pre></div>
</div>
<p>The output can be moved to a <code class="docutils literal"><span class="pre">std::basic_string</span></code> with <code class="docutils literal"><span class="pre">out.move_to()</span></code>.</p>
</p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator">
<span id="fmt::BasicStringWriter::BasicStringWriter__AllocatorCR"></span><span class="target" id="formatclassfmt_1_1_basic_string_writer_1a39e60f775feda49e58964a9c540831fc"></span><code class="descname">BasicStringWriter</code><span class="sig-paren">(</span><em class="property">const</em> Allocator &amp;<em>allocator</em> = Allocator()<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt17BasicStringWriterE" title="fmt::BasicStringWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicStringWriter</span></code></a> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicStringWriter::move_to__std::basic_string:Char.std::char_traits:Char:.Allocator:R"></span><span class="target" id="formatclassfmt_1_1_basic_string_writer_1af5eb54db9a51ef610d55ecb858257fb0"></span>void <code class="descname">move_to</code><span class="sig-paren">(</span>std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Moves the buffer content to <em>str</em> clearing the buffer.</p>
</p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_container_writer"></span><em class="property">template </em>&lt;<em class="property">class</em> Container&gt;</dt>
<dt id="_CPPv2N3fmt20BasicContainerWriterE">
<span id="fmt::BasicContainerWriter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicContainerWriter</code><a class="headerlink" href="#_CPPv2N3fmt20BasicContainerWriterE" title="Permalink to this definition"></a></dt>
<dd><p><p>This class template provides operations for formatting and appending data
to a standard <em>container</em> like <code class="docutils literal"><span class="pre">std::vector</span></code> or <code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">vecformat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">dest</span><span class="p">,</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicCStringRef</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="n">format</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">ArgList</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">BasicContainerWriter</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">appender</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span>
<span class="n">appender</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">format</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">FMT_VARIADIC</span><span class="p">(</span><span class="kt">void</span><span class="p">,</span> <span class="n">vecformat</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">BasicCStringRef</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">);</span>
</pre></div>
</div>
</p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Container::value_type &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container">
<span id="fmt::BasicContainerWriter::BasicContainerWriter__ContainerR"></span><span class="target" id="formatclassfmt_1_1_basic_container_writer_1a1c5f521af91a36bf07d580d3b5e8fde4"></span><code class="descname">BasicContainerWriter</code><span class="sig-paren">(</span>Container &amp;<em>dest</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt20BasicContainerWriterE" title="fmt::BasicContainerWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicContainerWriter</span></code></a> object.</p>
</p>
</dd></dl>
</div>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3binEi">
<span id="fmt::bin__i"></span><span class="target" id="formatformat_8h_1aa3e8966d52b70224d46861fabd090e4b"></span>IntFormatSpec&lt;int, TypeSpec&lt;'b'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">bin</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3binEi" title="Permalink to this definition"></a></dt>
<span id="fmt::bin__i"></span><span class="target" id="formatformat_8h_1a760fce6f0963895343b50eec787f80db"></span>IntFormatSpec&lt;int, TypeSpec&lt;'b'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">bin</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3binEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 2. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3octEi">
<span id="fmt::oct__i"></span><span class="target" id="formatformat_8h_1a1d166c5b2242a6a0aefba5455c32a2b3"></span>IntFormatSpec&lt;int, TypeSpec&lt;'o'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">oct</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3octEi" title="Permalink to this definition"></a></dt>
<span id="fmt::oct__i"></span><span class="target" id="formatformat_8h_1a49d07603108a758be5cc6157f456e32d"></span>IntFormatSpec&lt;int, TypeSpec&lt;'o'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">oct</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3octEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 8. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3hexEi">
<span id="fmt::hex__i"></span><span class="target" id="formatformat_8h_1aaa926c5c42fbad5f5c98aaad84b9f66a"></span>IntFormatSpec&lt;int, TypeSpec&lt;'x'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hex</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3hexEi" title="Permalink to this definition"></a></dt>
<span id="fmt::hex__i"></span><span class="target" id="formatformat_8h_1a8451bad40c90c2ce2aa1a932851cf090"></span>IntFormatSpec&lt;int, TypeSpec&lt;'x'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hex</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3hexEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 16 using lower-case letters for the digits above 9. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt4hexuEi">
<span id="fmt::hexu__i"></span><span class="target" id="formatformat_8h_1ac2fd8f73cfcd1321dfb6fb0302f23f66"></span>IntFormatSpec&lt;int, TypeSpec&lt;'X'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hexu</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt4hexuEi" title="Permalink to this definition"></a></dt>
<span id="fmt::hexu__i"></span><span class="target" id="formatformat_8h_1ae08e783a599e0667dae7b5a63a265de4"></span>IntFormatSpec&lt;int, TypeSpec&lt;'X'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hexu</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt4hexuEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer formatter format specifier to format in base 16 using upper-case letters for the digits above 9. </p>
</dd></dl>
@@ -797,7 +1042,7 @@ size known at compile time.</p>
<dt>
<em class="property">template </em>&lt;char <em>TYPE_CODE</em>, <em class="property">typename</em> Char&gt;</dt>
<dt id="_CPPv2N3fmt3padEij4Char">
<span id="fmt::pad__i.unsigned.Char"></span><span class="target" id="formatformat_8h_1a48d6010061d1710d807853ad9125d825"></span>IntFormatSpec&lt;int, AlignTypeSpec&lt;TYPE_CODE&gt;, Char&gt; <code class="descclassname">fmt::</code><code class="descname">pad</code><span class="sig-paren">(</span>int <em>value</em>, unsigned <em>width</em>, Char <em>fill</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3padEij4Char" title="Permalink to this definition"></a></dt>
<span id="fmt::pad__i.unsigned.Char"></span><span class="target" id="formatformat_8h_1aa6ebb90e2adc57f2c942e226fd708b24"></span>IntFormatSpec&lt;int, AlignTypeSpec&lt;TYPE_CODE&gt;, Char&gt; <code class="descclassname">fmt::</code><code class="descname">pad</code><span class="sig-paren">(</span>int <em>value</em>, unsigned <em>width</em>, Char <em>fill</em> = ' '<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3padEij4Char" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.</p>
@@ -817,7 +1062,7 @@ alignment.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> T&gt;</dt>
<dt id="_CPPv2N3fmt3argE9StringRefRK1T">
<span id="fmt::arg__StringRef.TCR"></span><span class="target" id="formatformat_8h_1a4649a895b3f769fe24b268e39a8cf152"></span>internal::NamedArg&lt;char&gt; <code class="descclassname">fmt::</code><code class="descname">arg</code><span class="sig-paren">(</span>StringRef <em>name</em>, <em class="property">const</em> T &amp;<em>arg</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="Permalink to this definition"></a></dt>
<span id="fmt::arg__StringRef.TCR"></span><span class="target" id="formatformat_8h_1a3ccc93714460459602dc6fc2b055ee6b"></span>internal::NamedArgWithType&lt;char, T&gt; <code class="descclassname">fmt::</code><code class="descname">arg</code><span class="sig-paren">(</span>StringRef <em>name</em>, <em class="property">const</em> T &amp;<em>arg</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns a named argument for formatting functions.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Elapsed time: {s:.2f} seconds&quot;</span><span class="p">,</span> <span class="n">arg</span><span class="p">(</span><span class="s">&quot;s&quot;</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">));</span>
@@ -826,18 +1071,10 @@ alignment.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">
<span class="target" id="formatformat_8h_1a1f0ec67406a0e4937166e6481f481198"></span>internal::UdlArg&lt;char&gt; <code class="descclassname">fmt::literals::</code><code class="descname">operator&quot;&quot;_a</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>s</em>, std::size_t<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>C++11 literal equivalent of <a class="reference internal" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="fmt::arg"><code class="xref cpp cpp-func docutils literal"><span class="pre">fmt::arg()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">fmt</span><span class="o">::</span><span class="n">literals</span><span class="p">;</span>
<span class="n">print</span><span class="p">(</span><span class="s">&quot;Elapsed time: {s:.2f} seconds&quot;</span><span class="p">,</span> <span class="s">&quot;s&quot;</span><span class="n">_a</span><span class="o">=</span><span class="mf">1.23</span><span class="p">);</span>
</pre></div>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">doxygenfunction: Cannot find function &#8220;operator&#8221;&#8220;_a&#8221; in doxygen xml output for project &#8220;format&#8221; from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
</div>
</p>
</dd></dl>
<dl class="macro">
<dt id="c.FMT_CAPTURE">
<span class="target" id="formatformat_8h_1a3caa326fabdddb0e4fbcad7e5ec8bd37"></span><code class="descname">FMT_CAPTURE</code><span class="sig-paren">(</span>...<span class="sig-paren">)</span><a class="headerlink" href="#c.FMT_CAPTURE" title="Permalink to this definition"></a></dt>
@@ -886,23 +1123,39 @@ directly:</p>
<dt id="_CPPv2N3fmt7ArgListE">
<span id="fmt::ArgList"></span><span class="target" id="formatclassfmt_1_1_arg_list"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">ArgList</code><a class="headerlink" href="#_CPPv2N3fmt7ArgListE" title="Permalink to this definition"></a></dt>
<dd><p>An argument list. </p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt7ArgListixEj">
<span id="fmt::ArgList::subscript-operator__unsigned"></span><span class="target" id="formatclassfmt_1_1_arg_list_1ad2c2672388e003aa70d9c948ac8140cd"></span>internal::Arg <code class="descname">operator[]</code><span class="sig-paren">(</span>unsigned <em>index</em><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt7ArgListixEj" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt7ArgListixEj">
<span id="fmt::ArgList::subscript-operator__unsignedC"></span><span class="target" id="formatclassfmt_1_1_arg_list_1a9a717b2022170c8f2918141a80cc6eb2"></span>internal::Arg <code class="descname">operator[]</code><span class="sig-paren">(</span>unsigned <em>index</em><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt7ArgListixEj" title="Permalink to this definition"></a></dt>
<dd><p>Returns the argument at specified index. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="function">
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> T&gt;</dt>
<dt id="_CPPv2N3fmt9to_stringERK1T">
<span id="fmt::to_string__TCR"></span><span class="target" id="formatstring_8h_1abfd84051cd3673d750be5851ee93b05f"></span>std::string <code class="descclassname">fmt::</code><code class="descname">to_string</code><span class="sig-paren">(</span><em class="property">const</em> T &amp;<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt9to_stringERK1T" title="Permalink to this definition"></a></dt>
<dd><p><p>Converts <em>value</em> to <code class="docutils literal"><span class="pre">std::string</span></code> using the default format for type <em>T</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;fmt/string.h&quot;</span><span class="cp"></span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">answer</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_string_ref"></span><em class="property">template </em>&lt;typename <em>Char</em>&gt;</dt>
<dt id="_CPPv2N3fmt14BasicStringRefE">
<span id="fmt::BasicStringRef"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicStringRef</code><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>A string reference. It can be constructed from a C string or <code class="docutils literal"><span class="pre">std::string</span></code>.</p>
<dd><p><p>A string reference. It can be constructed from a C string or
<code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p>You can use one of the following typedefs for common character types:</p>
<table border="1" class="docutils">
<colgroup>
@@ -933,7 +1186,7 @@ different types of strings to a function, for example:</p>
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">
@@ -950,28 +1203,30 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE">
<span id="fmt::BasicStringRef::BasicStringRef__std::basic_string:Char:CR"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1afd8ffd0c6d2ccac657f277a4faea3889"></span><code class="descname">BasicStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> Allocator&gt;</dt>
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicStringRef::BasicStringRef__std::basic_string:Char.std::char_traits:Char:.Allocator:CR"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a7c4c0c3bfc4768d7cb657f5756549863"></span><code class="descname">BasicStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from a <code class="docutils literal"><span class="pre">std::basic_string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef9to_stringEv">
<span id="fmt::BasicStringRef::to_string"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a7340f48f53cf9188e9fea5e6e1556969"></span>std::basic_string&lt;Char&gt; <code class="descname">to_string</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef9to_stringEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef9to_stringEv">
<span id="fmt::BasicStringRef::to_stringC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a85503c30cd35cd6deff9e77da52857e6"></span>std::basic_string&lt;Char&gt; <code class="descname">to_string</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef9to_stringEv" title="Permalink to this definition"></a></dt>
<dd><p><p>Converts a string reference to an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef4dataEv">
<span id="fmt::BasicStringRef::data"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1ae9c80502c527437215fe1c11dca8b475"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef4dataEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef4dataEv">
<span id="fmt::BasicStringRef::dataC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1aeca62faae1111525b0ef2667e75187f7"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef4dataEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the string data. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef4sizeEv">
<span id="fmt::BasicStringRef::size"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1ae38d9106dd5bec69488e5464aedc266a"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef4sizeEv">
<span id="fmt::BasicStringRef::sizeC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a765ddcb00e0a0a880a4a9458f9e68ea0"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the string size. </p>
</dd></dl>
@@ -984,7 +1239,7 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
<dt id="_CPPv2N3fmt15BasicCStringRefE">
<span id="fmt::BasicCStringRef"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicCStringRef</code><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>A reference to a null terminated string. It can be constructed from a C
string or <code class="docutils literal"><span class="pre">std::string</span></code>.</p>
string or <code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p>You can use one of the following typedefs for common character types:</p>
<table border="1" class="docutils">
<colgroup>
@@ -1015,7 +1270,7 @@ different types of strings to a function, for example:</p>
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">
@@ -1024,15 +1279,17 @@ different types of strings to a function, for example:</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE">
<span id="fmt::BasicCStringRef::BasicCStringRef__std::basic_string:Char:CR"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ab460855d19c769773de532296f9f13f9"></span><code class="descname">BasicCStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> Allocator&gt;</dt>
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicCStringRef::BasicCStringRef__std::basic_string:Char.std::char_traits:Char:.Allocator:CR"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1aa7caaa44a192e0184031d60c2a71bd12"></span><code class="descname">BasicCStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from a <code class="docutils literal"><span class="pre">std::basic_string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef5c_strEv">
<span id="fmt::BasicCStringRef::c_str"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ae3bafa845b53339b20c4f5edb4f635f9"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef5c_strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt15BasicCStringRef5c_strEv">
<span id="fmt::BasicCStringRef::c_strC"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ac1064b18371a8762e3d89395d253d436"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt15BasicCStringRef5c_strEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the pointer to a C string. </p>
</dd></dl>
@@ -1046,17 +1303,18 @@ different types of strings to a function, for example:</p>
<span id="fmt::Buffer"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">Buffer</code><a class="headerlink" href="#_CPPv2N3fmt6BufferE" title="Permalink to this definition"></a></dt>
<dd><p><p>A buffer supporting a subset of <code class="docutils literal"><span class="pre">std::vector</span></code>&#8216;s operations.</p>
</p>
<div class="breathe-sectiondef container">
<p>Subclassed by fmt::internal::MemoryBuffer&lt; T, SIZE, Allocator &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer4sizeEv">
<span id="fmt::Buffer::size"></span><span class="target" id="formatclassfmt_1_1_buffer_1a14fa72f0ddf584c14ffffb1446f598aa"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt6Buffer4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt6Buffer4sizeEv">
<span id="fmt::Buffer::sizeC"></span><span class="target" id="formatclassfmt_1_1_buffer_1a2489cffd9cdc6f846cdf17988d52f785"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt6Buffer4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the size of this buffer. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer8capacityEv">
<span id="fmt::Buffer::capacity"></span><span class="target" id="formatclassfmt_1_1_buffer_1aaf54fe786de91157629f96380e0cb215"></span>std::size_t <code class="descname">capacity</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt6Buffer8capacityEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt6Buffer8capacityEv">
<span id="fmt::Buffer::capacityC"></span><span class="target" id="formatclassfmt_1_1_buffer_1af38a0b9f1afac4901f24a73207f72e6f"></span>std::size_t <code class="descname">capacity</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt6Buffer8capacityEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the capacity of this buffer. </p>
</dd></dl>
@@ -1083,11 +1341,11 @@ different types of strings to a function, for example:</p>
</dd></dl>
</div>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Protected Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer4growENSt6size_tE">
<span id="fmt::Buffer::grow__std::s"></span>virtual <span class="target" id="formatclassfmt_1_1_buffer_1abdc7aaf5813aa07008b3d715969a7e19"></span>void <code class="descname">grow</code><span class="sig-paren">(</span>std::size_t <em>size</em><span class="sig-paren">)</span> = 0<a class="headerlink" href="#_CPPv2N3fmt6Buffer4growENSt6size_tE" title="Permalink to this definition"></a></dt>
<span id="fmt::Buffer::grow__std::s"></span><span class="target" id="formatclassfmt_1_1_buffer_1abdc7aaf5813aa07008b3d715969a7e19"></span><em class="property">virtual</em> void <code class="descname">grow</code><span class="sig-paren">(</span>std::size_t <em>size</em><span class="sig-paren">)</span> = 0<a class="headerlink" href="#_CPPv2N3fmt6Buffer4growENSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>Increases the buffer capacity to hold at least <em>size</em> elements updating
<code class="docutils literal"><span class="pre">ptr_</span></code> and <code class="docutils literal"><span class="pre">capacity_</span></code>.</p>
</p>
@@ -1103,21 +1361,17 @@ different types of strings to a function, for example:</p>
<dt id="_CPPv2N3fmt11SystemErrorE">
<span id="fmt::SystemError"></span><span class="target" id="formatclassfmt_1_1_system_error"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">SystemError</code><a class="headerlink" href="#_CPPv2N3fmt11SystemErrorE" title="Permalink to this definition"></a></dt>
<dd><p>An error returned by an operating system or a language runtime, for example a file opening error. </p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::RuntimeError</p>
<p>Subclassed by <a class="reference internal" href="#formatclassfmt_1_1_windows_error"><span class="std std-ref">fmt::WindowsError</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt11SystemError11SystemErrorEi10CStringRef">
<span id="fmt::SystemError::SystemError__i.CStringRef"></span><span class="target" id="formatclassfmt_1_1_system_error_1a307c40b2542f53d7426b09319255d35c"></span><code class="descname">SystemError</code><span class="sig-paren">(</span>int <em>error_code</em>, CStringRef <em>message</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11SystemError11SystemErrorEi10CStringRef" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt11SystemErrorE" title="fmt::SystemError"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::SystemError</span></code></a> object with the description
of the form</p>
<pre class="literal-block">
<em>&lt;message&gt;</em>: <em>&lt;system-message&gt;</em>
</pre>
<p>where <em>&lt;message&gt;</em> is the formatted message and <em>&lt;system-message&gt;</em> is
the system message corresponding to the error code.
<em>error_code</em> is a system error code as given by <code class="docutils literal"><span class="pre">errno</span></code>.
If <em>error_code</em> is not a valid error code such as -1, the system message
may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt11SystemErrorE" title="fmt::SystemError"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::SystemError</span></code></a> object with a description
formatted with <a class="reference internal" href="#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE" title="fmt::format_system_error"><code class="xref cpp cpp-any docutils literal"><span class="pre">fmt::format_system_error()</span></code></a>. <em>message</em> and additional
arguments passed into the constructor are formatted similarly to
<a class="reference internal" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="fmt::format"><code class="xref cpp cpp-any docutils literal"><span class="pre">fmt::format()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="c1">// This throws a SystemError with the description</span>
<span class="c1">// cannot open file &#39;madeup&#39;: No such file or directory</span>
@@ -1134,11 +1388,29 @@ may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
</div>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE">
<span id="fmt::format_system_error__fmt::WriterR.i.fmt::StringRef"></span><span class="target" id="formatformat_8h_1a3933879503d45e8cce0ef1e284f98402"></span>void <code class="descclassname">fmt::</code><code class="descname">format_system_error</code><span class="sig-paren">(</span>fmt::Writer &amp;<em>out</em>, int <em>error_code</em>, fmt::StringRef <em>message</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>Formats an error returned by an operating system or a language runtime,
for example a file opening error, and writes it to <em>out</em> in the following
form:</p>
<pre class="literal-block">
<em>&lt;message&gt;</em>: <em>&lt;system-message&gt;</em>
</pre>
<p>where <em>&lt;message&gt;</em> is the passed message and <em>&lt;system-message&gt;</em> is
the system message corresponding to the error code.
<em>error_code</em> is a system error code as given by <code class="docutils literal"><span class="pre">errno</span></code>.
If <em>error_code</em> is not a valid error code such as -1, the system message
may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
</p>
</dd></dl>
<dl class="class">
<dt id="_CPPv2N3fmt12WindowsErrorE">
<span id="fmt::WindowsError"></span><span class="target" id="formatclassfmt_1_1_windows_error"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">WindowsError</code><a class="headerlink" href="#_CPPv2N3fmt12WindowsErrorE" title="Permalink to this definition"></a></dt>
<dd><p>A Windows error. </p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_system_error"><span class="std std-ref">fmt::SystemError</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt12WindowsError12WindowsErrorEi10CStringRef">
@@ -1183,7 +1455,8 @@ A custom allocator class can be specified as a template argument to
</div>
<p>It is also possible to write a formatting function that uses a custom
allocator:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">basic_string</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">char_traits</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">&gt;</span> <span class="n">CustomString</span><span class="p">;</span>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">basic_string</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">char_traits</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">&gt;</span>
<span class="n">CustomString</span><span class="p">;</span>
<span class="n">CustomString</span> <span class="nf">format</span><span class="p">(</span><span class="n">CustomAllocator</span> <span class="n">alloc</span><span class="p">,</span> <span class="n">fmt</span><span class="o">::</span><span class="n">CStringRef</span> <span class="n">format_str</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">ArgList</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
@@ -1206,7 +1479,7 @@ allocator:</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+27 -16
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contents &mdash; fmt 3.0.0 documentation</title>
<title>Contents &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,18 +65,23 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
<li class="active"><a href="contents.html">Contents <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="contents.html">Contents
<span class="sr-only">(current)</span></a></li>
@@ -91,9 +99,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -120,6 +130,7 @@
<ul>
<li class="toctree-l1"><a class="reference internal" href="usage.html">Usage</a><ul>
<li class="toctree-l2"><a class="reference internal" href="usage.html#building-the-library">Building the library</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#header-only-usage-with-cmake">Header-only usage with CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#building-the-documentation">Building the documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#android-ndk">Android NDK</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#homebrew">Homebrew</a></li>
@@ -151,7 +162,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+114 -37
View File
@@ -9,7 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index &mdash; fmt 3.0.0 documentation</title>
<title>Index &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -18,10 +18,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,13 +65,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -91,9 +98,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -141,7 +150,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt7ArgListixEj">fmt::ArgList::operator[] (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt7ArgListixEj">fmt::ArgList::operator[] (C++ function)</a>
</dt>
@@ -217,7 +226,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char">fmt::BasicArgFormatter::BasicArgFormatter (C++ function)</a>
<dt><a href="api.html#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char">fmt::BasicArgFormatter::BasicArgFormatter (C++ function)</a>
</dt>
@@ -233,15 +242,23 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt20BasicContainerWriterE">fmt::BasicContainerWriter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container">fmt::BasicContainerWriter::BasicContainerWriter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRefE">fmt::BasicCStringRef (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">fmt::BasicCStringRef::BasicCStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE">[1]</a>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">fmt::BasicCStringRef::BasicCStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">[1]</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef5c_strEv">fmt::BasicCStringRef::c_str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt15BasicCStringRef5c_strEv">fmt::BasicCStringRef::c_str (C++ function)</a>
</dt>
@@ -276,6 +293,34 @@
<dt><a href="api.html#_CPPv2N3fmt17BasicMemoryWriteraSERR17BasicMemoryWriter">fmt::BasicMemoryWriter::operator= (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatterE">fmt::BasicPrintfArgFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec">fmt::BasicPrintfArgFormatter::BasicPrintfArgFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb">fmt::BasicPrintfArgFormatter::visit_bool (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi">fmt::BasicPrintfArgFormatter::visit_char (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc">fmt::BasicPrintfArgFormatter::visit_cstring (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE">fmt::BasicPrintfArgFormatter::visit_custom (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv">fmt::BasicPrintfArgFormatter::visit_pointer (C++ function)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
@@ -283,19 +328,31 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4Char">fmt::BasicStringRef::BasicStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">[1]</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE">[2]</a>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4Char">fmt::BasicStringRef::BasicStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">[1]</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">[2]</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef4dataEv">fmt::BasicStringRef::data (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef4dataEv">fmt::BasicStringRef::data (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef4sizeEv">fmt::BasicStringRef::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef4sizeEv">fmt::BasicStringRef::size (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef9to_stringEv">fmt::BasicStringRef::to_string (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef9to_stringEv">fmt::BasicStringRef::to_string (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriterE">fmt::BasicStringWriter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator">fmt::BasicStringWriter::BasicStringWriter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">fmt::BasicStringWriter::move_to (C++ function)</a>
</dt>
@@ -303,11 +360,11 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter5c_strEv">fmt::BasicWriter::c_str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter5c_strEv">fmt::BasicWriter::c_str (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter4dataEv">fmt::BasicWriter::data (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter4dataEv">fmt::BasicWriter::data (C++ function)</a>
</dt>
@@ -315,11 +372,11 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter4sizeEv">fmt::BasicWriter::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter4sizeEv">fmt::BasicWriter::size (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter3strEv">fmt::BasicWriter::str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter3strEv">fmt::BasicWriter::str (C++ function)</a>
</dt>
@@ -343,7 +400,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt6Buffer8capacityEv">fmt::Buffer::capacity (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt6Buffer8capacityEv">fmt::Buffer::capacity (C++ function)</a>
</dt>
@@ -359,7 +416,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt6Buffer4sizeEv">fmt::Buffer::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt6Buffer4sizeEv">fmt::Buffer::size (C++ function)</a>
</dt>
@@ -367,6 +424,10 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE">fmt::format_system_error (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">fmt::fprintf (C++ function)</a>, <a href="api.html#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">[1]</a>
</dt>
@@ -379,14 +440,6 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">fmt::literals::operator&#34;&#34;_a (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">fmt::literals::operator&#34;&#34;_format (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt3octEi">fmt::oct (C++ function)</a>
</dt>
@@ -403,6 +456,26 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt18PrintfArgFormatterE">fmt::PrintfArgFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec">fmt::PrintfArgFormatter::PrintfArgFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatterE">fmt::PrintfFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE">fmt::PrintfFormatter::format (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE">fmt::PrintfFormatter::PrintfFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt7sprintfE10CStringRef7ArgList">fmt::sprintf (C++ function)</a>
</dt>
@@ -415,6 +488,10 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt9to_stringERK1T">fmt::to_string (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt12WindowsErrorE">fmt::WindowsError (C++ class)</a>
</dt>
@@ -443,7 +520,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+72 -47
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Overview &mdash; fmt 3.0.0 documentation</title>
<title>Overview &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -33,8 +34,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -48,7 +50,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -61,13 +64,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -90,9 +97,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -105,20 +114,33 @@
</div>
</nav>
<div class="jumbotron">
<div class="tb-container">
<h1>{fmt}</h1>
<p class="lead">Small, safe and fast formatting library</p>
<div class="btn-group" role="group">
<a class="btn btn-success"
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
href="https://github.com/fmtlib/fmt/releases/download/4.0.0/fmt-4.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
</a>
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<button type="button" class="btn btn-success dropdown-toggle"
data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.0.0/cppformat-1.0.0.zip">Version 1.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/3.0.0/fmt-3.0.0.zip">Version 3.0.0
</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0
</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0
</a></li>
</ul>
</div>
</div>
@@ -140,16 +162,16 @@ alternative to C++ IOStreams.</p>
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
Thanks for creating this library. Its been a hole in C++ for a long time.
Ive used both boost::format and loki::SPrintf, and neither felt like the
right answer. This does.
Thanks for creating this library. Its been a hole in C++ for a long
time. Ive used both boost::format and loki::SPrintf, and neither felt
like the right answer. This does.
</div>
</div><div class="section" id="format-api">
<span id="id1"></span><h2>Format API<a class="headerlink" href="#format-api" title="Permalink to this headline"></a></h2>
<p>The replacement-based Format API provides a safe alternative to <code class="docutils literal"><span class="pre">printf</span></code>,
<code class="docutils literal"><span class="pre">sprintf</span></code> and friends with comparable or <a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">better performance</a>.
The <a class="reference external" href="doc/latest/index.html#format-string-syntax">format string syntax</a> is similar
to the one used by <a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
The <a class="reference external" href="syntax.html">format string syntax</a> is similar to the one used by
<a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
in Python:</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;The answer is {}&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
</pre></div>
@@ -202,8 +224,7 @@ literal operators, they must be made visible with the directive
</div>
<div class="section" id="write-api">
<span id="id2"></span><h2>Write API<a class="headerlink" href="#write-api" title="Permalink to this headline"></a></h2>
<p>The concatenation-based Write API (experimental) provides a
<a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">fast</a>
<p>The concatenation-based Write API (experimental) provides a <a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">fast</a>
stateless alternative to IOStreams:</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">MemoryWriter</span> <span class="n">out</span><span class="p">;</span>
<span class="n">out</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;The answer in hexadecimal is &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">hex</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
@@ -212,8 +233,9 @@ stateless alternative to IOStreams:</p>
</div>
<div class="section" id="safety">
<span id="id3"></span><h2>Safety<a class="headerlink" href="#safety" title="Permalink to this headline"></a></h2>
<p>The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code</p>
<p>The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;The answer is {:d}&quot;</span><span class="p">,</span> <span class="s">&quot;forty-two&quot;</span><span class="p">);</span>
</pre></div>
</div>
@@ -231,36 +253,38 @@ formatted into a narrow string. You can use a wide format string instead:</p>
</pre></div>
</div>
<p>For comparison, writing a wide character to <code class="docutils literal"><span class="pre">std::ostream</span></code> results in
its numeric value being written to the stream (i.e. 1070 instead of letter &#8216;ю&#8217; which
is represented by <code class="docutils literal"><span class="pre">L'\x42e'</span></code> if we use Unicode) which is rarely what is needed.</p>
its numeric value being written to the stream (i.e. 1070 instead of letter &#8216;ю&#8217;
which is represented by <code class="docutils literal"><span class="pre">L'\x42e'</span></code> if we use Unicode) which is rarely what is
needed.</p>
</div>
<div class="section" id="portability">
<span id="id4"></span><h2>Portability<a class="headerlink" href="#portability" title="Permalink to this headline"></a></h2>
<p>The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:</p>
<p>The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:</p>
<ul class="simple">
<li>64-bit (amd64) GNU/Linux with GCC 4.4.3, <a class="reference external" href="https://travis-ci.org/fmtlib/fmt">4.6.3</a>,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2</li>
<li>64-bit (amd64) GNU/Linux with GCC 4.4.3,
<a class="reference external" href="https://travis-ci.org/fmtlib/fmt">4.6.3</a>, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2</li>
<li>32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3</li>
<li>Mac OS X with GCC 4.2.1 and Clang 4.2, 5.1.0</li>
<li>64-bit Windows with Visual C++ 2010, 2013 and
<a class="reference external" href="https://ci.appveyor.com/project/vitaut/fmt">2015</a></li>
<li>32-bit Windows with Visual C++ 2010</li>
</ul>
<p>Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:</p>
<p>Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:</p>
<ul class="simple">
<li>Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.</li>
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.</li>
<li>User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
<code class="docutils literal"><span class="pre">_format</span></code> and <code class="docutils literal"><span class="pre">_a</span></code> are functionally equivalent to the functions
<code class="docutils literal"><span class="pre">fmt::format</span></code> and <code class="docutils literal"><span class="pre">fmt::arg</span></code>.</li>
</ul>
<p>The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the output
of <code class="docutils literal"><span class="pre">printf</span></code> is platform-dependent in this case. For example,</p>
<p>The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the
output of <code class="docutils literal"><span class="pre">printf</span></code> is platform-dependent in this case. For example,</p>
<div class="code highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;::</span><span class="n">infinity</span><span class="p">());</span>
</pre></div>
</div>
@@ -268,9 +292,10 @@ of <code class="docutils literal"><span class="pre">printf</span></code> is plat
</div>
<div class="section" id="ease-of-use">
<span id="id7"></span><h2>Ease of Use<a class="headerlink" href="#ease-of-use" title="Permalink to this headline"></a></h2>
<p>fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD <a class="reference external" href="https://github.com/fmtlib/fmt#license">license</a> allows using the library both
in open-source and commercial projects.</p>
<p>fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD <a class="reference external" href="https://github.com/fmtlib/fmt#license">license</a> allows
using the library both in open-source and commercial projects.</p>
<a class="btn btn-success" href="https://github.com/fmtlib/fmt">GitHub Repository</a>
<div class="section footer">
@@ -288,7 +313,7 @@ in open-source and commercial projects.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
Binary file not shown.
+24 -15
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search &mdash; fmt 3.0.0 documentation</title>
<title>Search &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -40,8 +41,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -56,7 +58,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -69,13 +72,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -126,9 +133,11 @@
containing fewer words won't appear in the result list.
</p>
<form class="form-inline" role="search" action="#" method="get">
<form class="form-inline" role="search" action="#"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" >
<input type="text" name="q" class="form-control"
>
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -149,7 +158,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
File diff suppressed because one or more lines are too long
+33 -25
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Format String Syntax &mdash; fmt 3.0.0 documentation</title>
<title>Format String Syntax &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,13 +65,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -85,15 +92,18 @@
<li class="active"><a href="syntax.html">Syntax <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="syntax.html">Syntax
<span class="sr-only">(current)</span></a></li>
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -153,12 +163,10 @@ precision and so on. Each value type can define its own &#8220;formatting
mini-language&#8221; or interpretation of the <em>format_spec</em>.</p>
<p>Most built-in types support a common formatting mini-language, which is
described in the next section.</p>
<p>A <em>format_spec</em> field can also include nested replacement fields within it.
These nested replacement fields can contain only an argument index;
format specifications are not allowed. Formatting is performed as if the
replacement fields within the format_spec are substituted before the
<em>format_spec</em> string is interpreted. This allows the formatting of a value
to be dynamically specified.</p>
<p>A <em>format_spec</em> field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.</p>
<p>See the <a class="reference internal" href="#formatexamples"><span class="std std-ref">Format examples</span></a> section for some examples.</p>
<div class="section" id="format-specification-mini-language">
<span id="formatspec"></span><h2>Format Specification Mini-Language<a class="headerlink" href="#format-specification-mini-language" title="Permalink to this headline"></a></h2>
@@ -176,8 +184,8 @@ although some of the formatting options are only supported by the numeric types.
<strong id="grammar-token-sign">sign </strong> ::= &quot;+&quot; | &quot;-&quot; | &quot; &quot;
<strong id="grammar-token-width">width </strong> ::= <a class="reference internal" href="#grammar-token-integer"><code class="xref docutils literal"><span class="pre">integer</span></code></a> | &quot;{&quot; <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> &quot;}&quot;
<strong id="grammar-token-precision">precision </strong> ::= <a class="reference internal" href="#grammar-token-integer"><code class="xref docutils literal"><span class="pre">integer</span></code></a> | &quot;{&quot; <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> &quot;}&quot;
<strong id="grammar-token-type">type </strong> ::= <a class="reference internal" href="#grammar-token-int_type"><code class="xref docutils literal"><span class="pre">int_type</span></code></a> | &quot;c&quot; | &quot;e&quot; | &quot;E&quot; | &quot;f&quot; | &quot;F&quot; | &quot;g&quot; | &quot;G&quot; | &quot;p&quot; | &quot;s&quot;
<strong id="grammar-token-int_type">int_type </strong> ::= &quot;b&quot; | &quot;B&quot; | &quot;d&quot; | &quot;o&quot; | &quot;x&quot; | &quot;X&quot;
<strong id="grammar-token-type">type </strong> ::= <a class="reference internal" href="#grammar-token-int_type"><code class="xref docutils literal"><span class="pre">int_type</span></code></a> | &quot;a&quot; | &quot;A&quot; | &quot;c&quot; | &quot;e&quot; | &quot;E&quot; | &quot;f&quot; | &quot;F&quot; | &quot;g&quot; | &quot;G&quot; | &quot;p&quot; | &quot;s&quot;
<strong id="grammar-token-int_type">int_type </strong> ::= &quot;b&quot; | &quot;B&quot; | &quot;d&quot; | &quot;n&quot; | &quot;o&quot; | &quot;x&quot; | &quot;X&quot;
</pre>
<p>The <em>fill</em> character can be any character other than &#8216;{&#8216; or &#8216;}&#8217;. The presence
of a fill character is signaled by the character following it, which must be
@@ -383,7 +391,7 @@ Boolean values are formatted using textual representation, either <code class="d
<tr class="row-even"><td><code class="docutils literal"><span class="pre">'a'</span></code></td>
<td>Hexadecimal floating point format. Prints the number in
base 16 with prefix <code class="docutils literal"><span class="pre">&quot;0x&quot;</span></code> and lower-case letters for
digits above 9. Uses &#8216;p&#8217; to indicate the exponent.</td>
digits above 9. Uses <code class="docutils literal"><span class="pre">'p'</span></code> to indicate the exponent.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal"><span class="pre">'A'</span></code></td>
<td>Same as <code class="docutils literal"><span class="pre">'a'</span></code> except it uses upper-case letters for
@@ -507,7 +515,7 @@ following examples.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+55 -21
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Usage &mdash; fmt 3.0.0 documentation</title>
<title>Usage &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -35,8 +36,9 @@
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'fmtlib.net');
ga('send', 'pageview');
@@ -50,7 +52,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -63,13 +66,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -78,7 +85,8 @@
<li class="active"><a href="usage.html">Usage <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="usage.html">Usage
<span class="sr-only">(current)</span></a></li>
@@ -92,9 +100,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -155,14 +165,38 @@ using Visual Studio or msbuild.</p>
</pre></div>
</div>
</div>
<div class="section" id="header-only-usage-with-cmake">
<h2>Header-only usage with CMake<a class="headerlink" href="#header-only-usage-with-cmake" title="Permalink to this headline"></a></h2>
<p>In order to add <code class="docutils literal"><span class="pre">fmtlib</span></code> into an existing <code class="docutils literal"><span class="pre">CMakeLists.txt</span></code> file, you can add the <code class="docutils literal"><span class="pre">fmt</span></code> library directory into your main project, which will enable the <code class="docutils literal"><span class="pre">fmt</span></code> library:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">add_subdirectory</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span>
</pre></div>
</div>
<p>If you have a project called <code class="docutils literal"><span class="pre">foo</span></code> that you would like to link against the fmt library in a header-only fashion, you can enable with with:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">target_link_libraries</span><span class="p">(</span><span class="n">foo</span> <span class="n">PRIVATE</span> <span class="n">fmt</span><span class="o">::</span><span class="n">fmt</span><span class="o">-</span><span class="n">header</span><span class="o">-</span><span class="n">only</span><span class="p">)</span>
</pre></div>
</div>
<p>And then to ensure that the <code class="docutils literal"><span class="pre">fmt</span></code> library does not always get built, you can modify the call to <code class="docutils literal"><span class="pre">add_subdirectory</span></code> to read</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">add_subdirectory</span><span class="p">(</span><span class="n">fmt</span> <span class="n">EXCLUDE_FROM_ALL</span><span class="p">)</span>
</pre></div>
</div>
<p>This will ensure that the <code class="docutils literal"><span class="pre">fmt</span></code> library is exluded from calls to <code class="docutils literal"><span class="pre">make</span></code>, <code class="docutils literal"><span class="pre">make</span> <span class="pre">all</span></code>, or <code class="docutils literal"><span class="pre">cmake</span> <span class="pre">--build</span> <span class="pre">.</span></code>.</p>
</div>
<div class="section" id="building-the-documentation">
<h2>Building the documentation<a class="headerlink" href="#building-the-documentation" title="Permalink to this headline"></a></h2>
<p>To build the documentation you need the following software installed on your
system:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</li>
<li><a class="reference external" href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a></li>
<li><a class="reference external" href="http://lesscss.org/">Less</a> with less-plugin-clean-css</li>
<ul>
<li><p class="first"><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</p>
</li>
<li><p class="first"><a class="reference external" href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a></p>
</li>
<li><p class="first"><a class="reference external" href="http://lesscss.org/">Less</a> with <code class="docutils literal"><span class="pre">less-plugin-clean-css</span></code>.
Ubuntu doesn&#8217;t package the <code class="docutils literal"><span class="pre">clean-css</span></code> plugin so you should use <code class="docutils literal"><span class="pre">npm</span></code>
instead of <code class="docutils literal"><span class="pre">apt</span></code> to install both <code class="docutils literal"><span class="pre">less</span></code> and the plugin:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">npm</span> <span class="n">install</span> <span class="o">-</span><span class="n">g</span> <span class="n">less</span> <span class="n">less</span><span class="o">-</span><span class="n">plugin</span><span class="o">-</span><span class="n">clean</span><span class="o">-</span><span class="n">css</span><span class="p">.</span>
</pre></div>
</div>
</li>
</ul>
<p>First generate makefiles or project files using CMake as described in
the previous section. Then compile the <code class="docutils literal"><span class="pre">doc</span></code> target/project, for example:</p>
@@ -182,7 +216,7 @@ repository.</p>
<div class="section" id="homebrew">
<h2>Homebrew<a class="headerlink" href="#homebrew" title="Permalink to this headline"></a></h2>
<p>fmt can be installed on OS X using <a class="reference external" href="http://brew.sh/">Homebrew</a>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">brew</span> <span class="n">install</span> <span class="n">cppformat</span>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">brew</span> <span class="n">install</span> <span class="n">fmt</span>
</pre></div>
</div>
</div>
@@ -197,7 +231,7 @@ repository.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+32 -29
View File
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
Thanks for creating this library. Its been a hole in C++ for a long time.
Ive used both boost::format and loki::SPrintf, and neither felt like the
right answer. This does.
Thanks for creating this library. Its been a hole in C++ for a long
time. Ive used both boost::format and loki::SPrintf, and neither felt
like the right answer. This does.
</div>
</div>
@@ -24,8 +24,8 @@ Format API
The replacement-based Format API provides a safe alternative to ``printf``,
``sprintf`` and friends with comparable or `better performance
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
The `format string syntax <syntax.html>`_ is similar to the one used by
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
in Python:
.. code:: c++
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
Write API
---------
The concatenation-based Write API (experimental) provides a
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
The concatenation-based Write API (experimental) provides a `fast
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
stateless alternative to IOStreams:
.. code:: c++
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
Safety
------
The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code
The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code
.. code:: c++
@@ -138,19 +139,21 @@ formatted into a narrow string. You can use a wide format string instead:
fmt::format(L"Cyrillic letter {}", L'\x42e');
For comparison, writing a wide character to ``std::ostream`` results in
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю' which
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
needed.
.. _portability:
Portability
-----------
The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:
The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:
* 64-bit (amd64) GNU/Linux with GCC 4.4.3, `4.6.3 <https://travis-ci.org/fmtlib/fmt>`_,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
`4.6.3 <https://travis-ci.org/fmtlib/fmt>`_, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2
* 32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3
@@ -161,21 +164,21 @@ compilers where it has been tested and known to work:
* 32-bit Windows with Visual C++ 2010
Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:
Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
``fmt::format`` and ``fmt::arg``.
The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives ``inf`` while the output
of ``printf`` is platform-dependent in this case. For example,
The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives ``inf`` while the
output of ``printf`` is platform-dependent in this case. For example,
.. code::
@@ -188,10 +191,10 @@ always prints ``inf``.
Ease of Use
-----------
fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD `license
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
in open-source and commercial projects.
fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
using the library both in open-source and commercial projects.
.. raw:: html
+7 -9
View File
@@ -49,12 +49,10 @@ mini-language" or interpretation of the *format_spec*.
Most built-in types support a common formatting mini-language, which is
described in the next section.
A *format_spec* field can also include nested replacement fields within it.
These nested replacement fields can contain only an argument index;
format specifications are not allowed. Formatting is performed as if the
replacement fields within the format_spec are substituted before the
*format_spec* string is interpreted. This allows the formatting of a value
to be dynamically specified.
A *format_spec* field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
sign: "+" | "-" | " "
width: `integer` | "{" `arg_id` "}"
precision: `integer` | "{" `arg_id` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "n" | "o" | "x" | "X"
The *fill* character can be any character other than '{' or '}'. The presence
of a fill character is signaled by the character following it, which must be
@@ -234,7 +232,7 @@ The available presentation types for floating-point values are:
+=========+==========================================================+
| ``'a'`` | Hexadecimal floating point format. Prints the number in |
| | base 16 with prefix ``"0x"`` and lower-case letters for |
| | digits above 9. Uses 'p' to indicate the exponent. |
| | digits above 9. Uses ``'p'`` to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'A'`` | Same as ``'a'`` except it uses upper-case letters for |
| | the prefix, digits above 9 and to indicate the exponent. |
+23 -2
View File
@@ -54,6 +54,23 @@ To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to
__ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries
Header-only usage with CMake
============================
In order to add ``fmtlib`` into an existing ``CMakeLists.txt`` file, you can add the ``fmt`` library directory into your main project, which will enable the ``fmt`` library::
add_subdirectory(fmt)
If you have a project called ``foo`` that you would like to link against the fmt library in a header-only fashion, you can enable with with::
target_link_libraries(foo PRIVATE fmt::fmt-header-only)
And then to ensure that the ``fmt`` library does not always get built, you can modify the call to ``add_subdirectory`` to read ::
add_subdirectory(fmt EXCLUDE_FROM_ALL)
This will ensure that the ``fmt`` library is exluded from calls to ``make``, ``make all``, or ``cmake --build .``.
Building the documentation
==========================
@@ -62,7 +79,11 @@ system:
* `Python <https://www.python.org/>`_ with pip and virtualenv
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
* `Less <http://lesscss.org/>`_ with less-plugin-clean-css
* `Less <http://lesscss.org/>`_ with ``less-plugin-clean-css``.
Ubuntu doesn't package the ``clean-css`` plugin so you should use ``npm``
instead of ``apt`` to install both ``less`` and the plugin::
sudo npm install -g less less-plugin-clean-css.
First generate makefiles or project files using CMake as described in
the previous section. Then compile the ``doc`` target/project, for example::
@@ -87,4 +108,4 @@ Homebrew
fmt can be installed on OS X using `Homebrew <http://brew.sh/>`_::
brew install cppformat
brew install fmt
+40 -14
View File
@@ -1,26 +1,52 @@
# Define the fmt library, its includes and the needed defines.
# format.cc is added to FMT_HEADERS for the header-only configuration.
set(FMT_HEADERS format.h format.cc ostream.h ostream.cc time.h)
# *.cc are added to FMT_HEADERS for the header-only configuration.
set(FMT_HEADERS container.h format.h format.cc ostream.h ostream.cc printf.h
printf.cc string.h time.h)
if (HAVE_OPEN)
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
endif ()
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} ../ChangeLog.rst)
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} ../README.rst ../ChangeLog.rst)
add_library(fmt::fmt ALIAS fmt)
option(FMT_CPPFORMAT "Build cppformat library for backward compatibility." OFF)
if (FMT_CPPFORMAT)
message(WARNING "The cppformat library is deprecated, use fmt instead.")
add_library(cppformat ${FMT_SOURCES} ${FMT_HEADERS})
# Starting with cmake 3.1 the CXX_STANDARD property can be used instead.
# Note: Don't make -std=c++11 public or interface, since it breaks projects
# that use C++14.
target_compile_options(fmt PRIVATE ${CPP11_FLAG})
if (FMT_PEDANTIC)
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
include_directories(fmt INTERFACE
target_include_directories(fmt PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
set_target_properties(fmt PROPERTIES
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
if (BUILD_SHARED_LIBS)
if (UNIX AND NOT APPLE)
# Fix rpmlint warning:
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
target_link_libraries(fmt -Wl,--as-needed)
endif ()
target_compile_definitions(fmt PRIVATE FMT_EXPORT INTERFACE FMT_SHARED)
endif ()
#------------------------------------------------------------------------------
# additionally define a header only library when cmake is new enough
if (CMAKE_VERSION VERSION_GREATER 3.1.0 OR CMAKE_VERSION VERSION_EQUAL 3.1.0)
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)
target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_include_directories(fmt-header-only INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
endif ()
# Install targets.
if (FMT_INSTALL)
include(CMakePackageConfigHelpers)
@@ -47,18 +73,18 @@ if (FMT_INSTALL)
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
${project_config}
INSTALL_DESTINATION ${FMT_CMAKE_DIR})
export(TARGETS ${INSTALL_TARGETS} FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt::
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
install(
FILES ${project_config} ${version_config}
DESTINATION ${FMT_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
NAMESPACE fmt::)
# Install the library and headers.
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name} DESTINATION ${FMT_LIB_DIR})
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
DESTINATION ${FMT_LIB_DIR})
install(FILES ${FMT_HEADERS} DESTINATION include/fmt)
if (FMT_CPPFORMAT)
install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR})
endif ()
endif ()
+82
View File
@@ -0,0 +1,82 @@
/*
Formatting library for C++ - standard container utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_CONTAINER_H_
#define FMT_CONTAINER_H_
#include "format.h"
namespace fmt {
namespace internal {
/**
\rst
A "buffer" that appends data to a standard container (e.g. typically a
``std::vector`` or ``std::basic_string``).
\endrst
*/
template <typename Container>
class ContainerBuffer : public Buffer<typename Container::value_type> {
private:
Container& container_;
protected:
virtual void grow(std::size_t size) FMT_OVERRIDE {
container_.resize(size);
this->ptr_ = &container_[0];
this->capacity_ = size;
}
public:
explicit ContainerBuffer(Container& container) : container_(container) {
this->size_ = container_.size();
if (this->size_ > 0) {
this->ptr_ = &container_[0];
this->capacity_ = this->size_;
}
}
};
} // namespace internal
/**
\rst
This class template provides operations for formatting and appending data
to a standard *container* like ``std::vector`` or ``std::basic_string``.
**Example**::
void vecformat(std::vector<char>& dest, fmt::BasicCStringRef<char> format,
fmt::ArgList args) {
fmt::BasicContainerWriter<std::vector<char> > appender(dest);
appender.write(format, args);
}
FMT_VARIADIC(void, vecformat, std::vector<char>&,
fmt::BasicCStringRef<char>);
\endrst
*/
template <class Container>
class BasicContainerWriter
: public BasicWriter<typename Container::value_type> {
private:
internal::ContainerBuffer<Container> buffer_;
public:
/**
\rst
Constructs a :class:`fmt::BasicContainerWriter` object.
\endrst
*/
explicit BasicContainerWriter(Container& dest)
: BasicWriter<typename Container::value_type>(buffer_), buffer_(dest) {}
};
} // namespace fmt
#endif // FMT_CONTAINER_H_
+67 -467
View File
@@ -41,6 +41,9 @@
#endif
#if FMT_USE_WINDOWS_H
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
# include <windows.h>
# else
@@ -50,8 +53,6 @@
# endif
#endif
using fmt::internal::Arg;
#if FMT_EXCEPTIONS
# define FMT_TRY try
# define FMT_CATCH(x) catch (x)
@@ -79,6 +80,11 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
}
namespace fmt {
FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
namespace {
#ifndef _MSC_VER
@@ -100,27 +106,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
# define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned>
struct IntChecker {
template <typename T>
static bool fits_in_int(T value) {
unsigned max = INT_MAX;
return value <= max;
}
static bool fits_in_int(bool) { return true; }
};
template <>
struct IntChecker<true> {
template <typename T>
static bool fits_in_int(T value) {
return value >= INT_MIN && value <= INT_MAX;
}
static bool fits_in_int(int) { return true; }
};
const char RESET_COLOR[] = "\x1b[0m";
typedef void (*FormatFunc)(Writer &, int, StringRef);
@@ -186,7 +171,8 @@ int safe_strerror(
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
int run() {
strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
// Suppress a warning about unused strerror_r.
strerror_r(0, FMT_NULL, "");
return handle(strerror_r(error_code_, buffer_, buffer_size_));
}
};
@@ -225,222 +211,19 @@ void report_error(FormatFunc func, int error_code,
std::fwrite(full_message.data(), full_message.size(), 1, stderr);
std::fputc('\n', stderr);
}
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
public:
template <typename T>
bool visit_any_int(T value) { return value == 0; }
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
private:
FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
void report_unhandled_arg() {
FMT_THROW(FormatError("width is not integer"));
}
template <typename T>
unsigned visit_any_int(T value) {
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value);
if (internal::is_negative(value)) {
spec_.align_ = ALIGN_LEFT;
width = 0 - width;
}
if (width > INT_MAX)
FMT_THROW(FormatError("number is too big"));
return static_cast<unsigned>(width);
}
};
class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
public:
void report_unhandled_arg() {
FMT_THROW(FormatError("precision is not integer"));
}
template <typename T>
int visit_any_int(T value) {
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big"));
return static_cast<int>(value);
}
};
template <typename T, typename U>
struct is_same {
enum { value = 0 };
};
template <typename T>
struct is_same<T, T> {
enum { value = 1 };
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
private:
internal::Arg &arg_;
wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public:
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {}
void visit_bool(bool value) {
if (type_ != 's')
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int)) {
// Extra casts are used to silence warnings.
if (is_signed) {
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
} else {
arg_.type = Arg::UINT;
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
}
} else {
if (is_signed) {
arg_.type = Arg::LONG_LONG;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_.long_long_value = static_cast<LongLong>(value);
} else {
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
}
}
}
};
// Converts an integer argument to char for printf.
class CharConverter : public ArgVisitor<CharConverter, void> {
private:
internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
template <typename T>
void visit_any_int(T value) {
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value);
}
};
} // namespace
namespace internal {
template <typename Char>
class PrintfArgFormatter :
public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
void write_null_pointer() {
this->spec().type_ = 0;
this->write("(nil)");
}
typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
public:
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
void visit_bool(bool value) {
FormatSpec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
this->write(value);
}
void visit_char(int value) {
const FormatSpec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
w.write_int(value, fmt_spec);
typedef typename BasicWriter<Char>::CharPtr CharPtr;
CharPtr out = CharPtr();
if (fmt_spec.width_ > 1) {
Char fill = ' ';
out = w.grow_buffer(fmt_spec.width_);
if (fmt_spec.align_ != ALIGN_LEFT) {
std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
} else {
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
}
} else {
out = w.grow_buffer(1);
}
*out = static_cast<Char>(value);
}
void visit_cstring(const char *value) {
if (value)
Base::visit_cstring(value);
else if (this->spec().type_ == 'p')
write_null_pointer();
else
this->write("(null)");
}
void visit_pointer(const void *value) {
if (value)
return Base::visit_pointer(value);
this->spec().type_ = 0;
write_null_pointer();
}
void visit_custom(Arg::CustomValue c) {
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = {'}', 0};
const Char *format = format_str;
c.format(&formatter, c.value, &format);
}
};
} // namespace internal
} // namespace fmt
FMT_FUNC void fmt::SystemError::init(
FMT_FUNC void SystemError::init(
int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code;
MemoryWriter w;
internal::format_system_error(w, err_code, format(format_str, args));
format_system_error(w, err_code, format(format_str, args));
std::runtime_error &base = *this;
base = std::runtime_error(w.str());
}
template <typename T>
int fmt::internal::CharTraits<char>::format_float(
int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, T value) {
if (width == 0) {
@@ -454,7 +237,7 @@ int fmt::internal::CharTraits<char>::format_float(
}
template <typename T>
int fmt::internal::CharTraits<wchar_t>::format_float(
int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, T value) {
if (width == 0) {
@@ -468,7 +251,7 @@ int fmt::internal::CharTraits<wchar_t>::format_float(
}
template <typename T>
const char fmt::internal::BasicData<T>::DIGITS[] =
const char internal::BasicData<T>::DIGITS[] =
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
@@ -487,40 +270,40 @@ const char fmt::internal::BasicData<T>::DIGITS[] =
factor * 1000000000
template <typename T>
const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
0, FMT_POWERS_OF_10(1)
};
template <typename T>
const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
0,
FMT_POWERS_OF_10(1),
FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
FMT_POWERS_OF_10(ULongLong(1000000000)),
// Multiply several constants instead of using a single long long constant
// to avoid warnings about C++98 not supporting long long.
fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
ULongLong(1000000000) * ULongLong(1000000000) * 10
};
FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
(void)type;
if (std::isprint(static_cast<unsigned char>(code))) {
FMT_THROW(fmt::FormatError(
fmt::format("unknown format code '{}' for {}", code, type)));
FMT_THROW(FormatError(
format("unknown format code '{}' for {}", code, type)));
}
FMT_THROW(fmt::FormatError(
fmt::format("unknown format code '\\x{:02x}' for {}",
FMT_THROW(FormatError(
format("unknown format code '\\x{:02x}' for {}",
static_cast<unsigned>(code), type)));
}
#if FMT_USE_WINDOWS_H
FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
if (s.size() > INT_MAX)
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
int s_size = static_cast<int>(s.size());
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1);
@@ -531,30 +314,31 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
buffer_[length] = 0;
}
FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
if (int error_code = convert(s)) {
FMT_THROW(WindowsError(error_code,
"cannot convert string from UTF-16 to UTF-8"));
}
}
FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
if (s.size() > INT_MAX)
return ERROR_INVALID_PARAMETER;
int s_size = static_cast<int>(s.size());
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
int length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_.resize(length + 1);
length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_[length] = 0;
return 0;
}
FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void WindowsError::init(
int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code;
MemoryWriter w;
@@ -563,17 +347,17 @@ FMT_FUNC void fmt::WindowsError::init(
base = std::runtime_error(w.str());
}
FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
FMT_FUNC void internal::format_windows_error(
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
for (;;) {
wchar_t *system_message = &buffer[0];
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), 0);
int result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
if (result != 0) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@@ -592,12 +376,11 @@ FMT_FUNC void fmt::internal::format_windows_error(
#endif // FMT_USE_WINDOWS_H
FMT_FUNC void fmt::internal::format_system_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
FMT_FUNC void format_system_error(
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
buffer.resize(internal::INLINE_BUFFER_SIZE);
for (;;) {
char *system_message = &buffer[0];
int result = safe_strerror(error_code, system_message, buffer.size());
@@ -614,11 +397,11 @@ FMT_FUNC void fmt::internal::format_system_error(
}
template <typename Char>
void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
void internal::ArgMap<Char>::init(const ArgList &args) {
if (!map_.empty())
return;
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = 0;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
if (use_values) {
@@ -659,18 +442,18 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
}
template <typename Char>
void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
void internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
}
FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg(
unsigned arg_index, const char *&error) {
Arg arg = args_[arg_index];
internal::Arg arg = args_[arg_index];
switch (arg.type) {
case Arg::NONE:
case internal::Arg::NONE:
error = "argument index out of range";
break;
case Arg::NAMED_ARG:
case internal::Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer);
break;
default:
@@ -679,203 +462,31 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
return arg;
}
template <typename Char>
void fmt::internal::PrintfFormatter<Char>::parse_flags(
FormatSpec &spec, const Char *&s) {
for (;;) {
switch (*s++) {
case '-':
spec.align_ = ALIGN_LEFT;
break;
case '+':
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
break;
case '0':
spec.fill_ = '0';
break;
case ' ':
spec.flags_ |= SIGN_FLAG;
break;
case '#':
spec.flags_ |= HASH_FLAG;
break;
default:
--s;
return;
}
}
}
template <typename Char>
Arg fmt::internal::PrintfFormatter<Char>::get_arg(
const Char *s, unsigned arg_index) {
(void)s;
const char *error = 0;
Arg arg = arg_index == UINT_MAX ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg;
}
template <typename Char>
unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
const Char *&s, FormatSpec &spec) {
unsigned arg_index = UINT_MAX;
Char c = *s;
if (c >= '0' && c <= '9') {
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned value = parse_nonnegative_int(s);
if (*s == '$') { // value is an argument index
++s;
arg_index = value;
} else {
if (c == '0')
spec.fill_ = '0';
if (value != 0) {
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec.width_ = value;
return arg_index;
}
}
}
parse_flags(spec, s);
// Parse width.
if (*s >= '0' && *s <= '9') {
spec.width_ = parse_nonnegative_int(s);
} else if (*s == '*') {
++s;
spec.width_ = WidthHandler(spec).visit(get_arg(s));
}
return arg_index;
}
template <typename Char>
void fmt::internal::PrintfFormatter<Char>::format(
BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
const Char *start = format_str.c_str();
const Char *s = start;
while (*s) {
Char c = *s++;
if (c != '%') continue;
if (*s == c) {
write(writer, start, s);
start = ++s;
continue;
}
write(writer, start, s - 1);
FormatSpec spec;
spec.align_ = ALIGN_RIGHT;
// Parse argument index, flags and width.
unsigned arg_index = parse_header(s, spec);
// Parse precision.
if (*s == '.') {
++s;
if ('0' <= *s && *s <= '9') {
spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
} else if (*s == '*') {
++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s));
}
}
Arg arg = get_arg(s, arg_index);
if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0') {
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
switch (*s++) {
case 'h':
if (*s == 'h')
ArgConverter<signed char>(arg, *++s).visit(arg);
else
ArgConverter<short>(arg, *s).visit(arg);
break;
case 'l':
if (*s == 'l')
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
else
ArgConverter<long>(arg, *s).visit(arg);
break;
case 'j':
ArgConverter<intmax_t>(arg, *s).visit(arg);
break;
case 'z':
ArgConverter<std::size_t>(arg, *s).visit(arg);
break;
case 't':
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break;
default:
--s;
ArgConverter<void>(arg, *s).visit(arg);
}
// Parse type.
if (!*s)
FMT_THROW(FormatError("invalid format string"));
spec.type_ = static_cast<char>(*s++);
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type.
switch (spec.type_) {
case 'i': case 'u':
spec.type_ = 'd';
break;
case 'c':
// TODO: handle wchar_t
CharConverter(arg).visit(arg);
break;
}
}
start = s;
// Format argument.
internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
}
write(writer, start, s);
}
FMT_FUNC void fmt::report_system_error(
FMT_FUNC void report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_system_error, error_code, message);
report_error(format_system_error, error_code, message);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC void fmt::report_windows_error(
FMT_FUNC void report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_windows_error, error_code, message);
report_error(internal::format_windows_error, error_code, message);
}
#endif
FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
std::fwrite(w.data(), 1, w.size(), f);
}
FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
FMT_FUNC void print(CStringRef format_str, ArgList args) {
print(stdout, format_str, args);
}
FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
char escape[] = "\x1b[30m";
escape[3] = static_cast<char>('0' + c);
std::fputs(escape, stdout);
@@ -883,53 +494,42 @@ FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
std::fputs(RESET_COLOR, stdout);
}
FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
std::size_t size = w.size();
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
#ifndef FMT_HEADER_ONLY
template struct fmt::internal::BasicData<void>;
template struct internal::BasicData<void>;
// Explicit instantiations for char.
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
template void internal::FixedBuffer<char>::grow(std::size_t);
template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
template void internal::ArgMap<char>::init(const ArgList &args);
template void fmt::internal::PrintfFormatter<char>::format(
BasicWriter<char> &writer, CStringRef format);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value);
// Explicit instantiations for wchar_t.
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
template void fmt::internal::PrintfFormatter<wchar_t>::format(
BasicWriter<wchar_t> &writer, WCStringRef format);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template FMT_API int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template FMT_API int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value);
#endif // FMT_HEADER_ONLY
} // namespace fmt
#ifdef _MSC_VER
# pragma warning(pop)
#endif
+409 -231
View File
File diff suppressed because it is too large Load Diff
+4 -30
View File
@@ -4,34 +4,15 @@
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For the license information refer to format.h.
*/
#include "ostream.h"
namespace fmt {
namespace {
// Write the content of w to os.
void write(std::ostream &os, Writer &w) {
namespace internal {
FMT_FUNC void write(std::ostream &os, Writer &w) {
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
@@ -49,13 +30,6 @@ void write(std::ostream &os, Writer &w) {
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
write(os, w);
}
FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
write(os, w);
return static_cast<int>(w.size());
internal::write(os, w);
}
} // namespace fmt
+22 -50
View File
@@ -4,25 +4,7 @@
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For the license information refer to format.h.
*/
#ifndef FMT_OSTREAM_H_
@@ -42,28 +24,27 @@ class FormatBuf : public std::basic_streambuf<Char> {
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
Buffer<Char> &buffer_;
Char *start_;
public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
this->setp(start_, start_ + buffer_.capacity());
}
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
int_type overflow(int_type ch = traits_type::eof()) {
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
size_t buf_size = size();
buffer_.resize(buf_size);
buffer_.reserve(buf_size * 2);
protected:
// The put-area is actually always empty. This makes the implementation
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
// to overflow. There is no disadvantage here for sputn since this always
// results in a call to xsputn.
start_ = &buffer_[0];
start_[buf_size] = traits_type::to_char_type(ch);
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
}
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.push_back(static_cast<Char>(ch));
return ch;
}
size_t size() const {
return to_unsigned(this->pptr() - start_);
std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
buffer_.append(s, s + count);
return count;
}
};
@@ -84,19 +65,22 @@ struct ConvertToIntImpl<T, true> {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
};
};
// Write the content of w to os.
FMT_API void write(std::ostream &os, Writer &w);
} // namespace internal
// Formats a value.
template <typename Char, typename ArgFormatter, typename T>
void format(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value) {
template <typename Char, typename ArgFormatter_, typename T>
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
const Char *&format_str, const T &value) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output << value;
BasicStringRef<Char> str(&buffer[0], format_buf.size());
BasicStringRef<Char> str(&buffer[0], buffer.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
@@ -112,18 +96,6 @@ void format(BasicFormatter<Char, ArgFormatter> &f,
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY
+21 -36
View File
@@ -1,28 +1,10 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2016, Victor Zverovich
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For the license information refer to format.h.
*/
// Disable bogus MSVC warnings.
@@ -39,6 +21,9 @@
#ifndef _WIN32
# include <unistd.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <io.h>
@@ -90,16 +75,16 @@ fmt::BufferedFile::BufferedFile(
fmt::CStringRef filename, fmt::CStringRef mode) {
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
if (!file_)
throw SystemError(errno, "cannot open file {}", filename);
FMT_THROW(SystemError(errno, "cannot open file {}", filename));
}
void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
file_ = 0;
file_ = FMT_NULL;
if (result != 0)
throw SystemError(errno, "cannot close file");
FMT_THROW(SystemError(errno, "cannot close file"));
}
// A macro used to prevent expansion of fileno on broken versions of MinGW.
@@ -108,7 +93,7 @@ void fmt::BufferedFile::close() {
int fmt::BufferedFile::fileno() const {
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
if (fd == -1)
throw SystemError(errno, "cannot get file descriptor");
FMT_THROW(SystemError(errno, "cannot get file descriptor"));
return fd;
}
@@ -121,7 +106,7 @@ fmt::File::File(fmt::CStringRef path, int oflag) {
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
#endif
if (fd_ == -1)
throw SystemError(errno, "cannot open file {}", path);
FMT_THROW(SystemError(errno, "cannot open file {}", path));
}
fmt::File::~File() FMT_NOEXCEPT {
@@ -139,7 +124,7 @@ void fmt::File::close() {
int result = FMT_POSIX_CALL(close(fd_));
fd_ = -1;
if (result != 0)
throw SystemError(errno, "cannot close file");
FMT_THROW(SystemError(errno, "cannot close file"));
}
fmt::LongLong fmt::File::size() const {
@@ -153,7 +138,7 @@ fmt::LongLong fmt::File::size() const {
if (size_lower == INVALID_FILE_SIZE) {
DWORD error = GetLastError();
if (error != NO_ERROR)
throw WindowsError(GetLastError(), "cannot get file size");
FMT_THROW(WindowsError(GetLastError(), "cannot get file size"));
}
fmt::ULongLong long_size = size_upper;
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
@@ -161,7 +146,7 @@ fmt::LongLong fmt::File::size() const {
typedef struct stat Stat;
Stat file_stat = Stat();
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
throw SystemError(errno, "cannot get file attributes");
FMT_THROW(SystemError(errno, "cannot get file attributes"));
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
"return type of File::size is not large enough");
return file_stat.st_size;
@@ -172,7 +157,7 @@ std::size_t fmt::File::read(void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot read from file");
FMT_THROW(SystemError(errno, "cannot read from file"));
return internal::to_unsigned(result);
}
@@ -180,7 +165,7 @@ std::size_t fmt::File::write(const void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot write to file");
FMT_THROW(SystemError(errno, "cannot write to file"));
return internal::to_unsigned(result);
}
@@ -189,7 +174,7 @@ fmt::File fmt::File::dup(int fd) {
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int new_fd = FMT_POSIX_CALL(dup(fd));
if (new_fd == -1)
throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd));
return File(new_fd);
}
@@ -197,8 +182,8 @@ void fmt::File::dup2(int fd) {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) {
throw SystemError(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd);
FMT_THROW(SystemError(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd));
}
}
@@ -225,7 +210,7 @@ void fmt::File::pipe(File &read_end, File &write_end) {
int result = FMT_POSIX_CALL(pipe(fds));
#endif
if (result != 0)
throw SystemError(errno, "cannot create pipe");
FMT_THROW(SystemError(errno, "cannot create pipe"));
// The following assignments don't throw because read_fd and write_fd
// are closed.
read_end = File(fds[0]);
@@ -236,7 +221,7 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) {
// Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f)
throw SystemError(errno, "cannot associate stream with file descriptor");
FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor"));
BufferedFile file(f);
fd_ = -1;
return file;
@@ -250,7 +235,7 @@ long fmt::getpagesize() {
#else
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
if (size < 0)
throw SystemError(errno, "cannot get memory page size");
FMT_THROW(SystemError(errno, "cannot get memory page size"));
return size;
#endif
}

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