mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 17:05:44 +01:00
Merge pull request #14317 from Naios/typesafelog
Type safe logging
(cherry picked from commit cc0c9add5a)
Conflicts:
src/server/bnetserver/CMakeLists.txt
src/server/game/Server/WorldSocketMgr.cpp
src/server/shared/Logging/AppenderDB.cpp
src/server/worldserver/CMakeLists.txt
This commit is contained in:
35
dep/cppformat/CMakeLists.txt
Normal file
35
dep/cppformat/CMakeLists.txt
Normal file
@@ -0,0 +1,35 @@
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
set(FMT_SOURCES format.cc format.h)
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set_target_properties(format PROPERTIES COMPILE_FLAGS
|
||||
"-Wall -Wextra -Wshadow -pedantic")
|
||||
endif ()
|
||||
|
||||
# Use variadic templates
|
||||
add_definitions(-DFMT_VARIADIC_TEMPLATES=1)
|
||||
|
||||
# Check if initializer lists are supported.
|
||||
check_cxx_source_compiles("
|
||||
#include <initilizer_list>
|
||||
int main() {}" FMT_INITIALIZER_LIST)
|
||||
|
||||
# Use delete
|
||||
add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1)
|
||||
|
||||
# Use static assert
|
||||
add_definitions(-DFMT_USE_STATIC_ASSERT=1)
|
||||
|
||||
if (WIN32)
|
||||
check_symbol_exists(open io.h HAVE_OPEN)
|
||||
else ()
|
||||
check_symbol_exists(open fcntl.h HAVE_OPEN)
|
||||
endif ()
|
||||
if (HAVE_OPEN)
|
||||
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
|
||||
set(FMT_SOURCES ${FMT_SOURCES} posix.cc posix.h)
|
||||
endif ()
|
||||
|
||||
add_library(format STATIC ${FMT_SOURCES})
|
||||
335
dep/cppformat/ChangeLog.rst
Normal file
335
dep/cppformat/ChangeLog.rst
Normal file
@@ -0,0 +1,335 @@
|
||||
1.1.0 - 2015-03-06
|
||||
------------------
|
||||
|
||||
* Added ``BasicArrayWriter``, a class template that provides operations for
|
||||
formatting and writing data into a fixed-size array
|
||||
(`#105 <https://github.com/cppformat/cppformat/issues/105>`_ and
|
||||
`#122 <https://github.com/cppformat/cppformat/issues/122>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
char buffer[100];
|
||||
fmt::ArrayWriter w(buffer);
|
||||
w.write("The answer is {}", 42);
|
||||
|
||||
* Added `0 A.D. <http://play0ad.com/>`_ and `PenUltima Online (POL)
|
||||
<http://www.polserver.com/>`_ to the list of notable projects using C++ Format.
|
||||
|
||||
* C++ Format now uses MSVC intrinsics for better formatting performance
|
||||
(`#115 <https://github.com/cppformat/cppformat/pull/115>`_,
|
||||
`#116 <https://github.com/cppformat/cppformat/pull/116>`_,
|
||||
`#118 <https://github.com/cppformat/cppformat/pull/118>`_ and
|
||||
`#121 <https://github.com/cppformat/cppformat/pull/121>`_).
|
||||
Previously these optimizations where only used on GCC and Clang.
|
||||
Thanks to `@CarterLi <https://github.com/CarterLi>`_ and
|
||||
`@objectx <https://github.com/objectx>`_.
|
||||
|
||||
* CMake install target (`#119 <https://github.com/cppformat/cppformat/pull/119>`_).
|
||||
Thanks to `@TrentHouliston <https://github.com/TrentHouliston>`_.
|
||||
|
||||
You can now install C++ Format with ``make install`` command.
|
||||
|
||||
* Improved `Biicode <http://www.biicode.com/>`_ support
|
||||
(`#98 <https://github.com/cppformat/cppformat/pull/98>`_ and
|
||||
`#104 <https://github.com/cppformat/cppformat/pull/104>`_). Thanks to
|
||||
`@MariadeAnton <https://github.com/MariadeAnton>`_ and
|
||||
`@franramirez688 <https://github.com/franramirez688>`_.
|
||||
|
||||
* Improved support for bulding with `Android NDK
|
||||
<https://developer.android.com/tools/sdk/ndk/index.html>`_
|
||||
(`#107 <https://github.com/cppformat/cppformat/pull/107>`_).
|
||||
Thanks to `@newnon <https://github.com/newnon>`_.
|
||||
|
||||
The `android-ndk-example <https://github.com/cppformat/android-ndk-example>`_
|
||||
repository provides and example of using C++ Format with Android NDK:
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/cppformat/android-ndk-example/
|
||||
master/screenshot.png
|
||||
|
||||
* Improved documentation of ``SystemError`` and ``WindowsError``
|
||||
(`#54 <https://github.com/cppformat/cppformat/issues/54>`_).
|
||||
|
||||
* Various code improvements
|
||||
(`#110 <https://github.com/cppformat/cppformat/pull/110>`_,
|
||||
`#111 <https://github.com/cppformat/cppformat/pull/111>`_
|
||||
`#112 <https://github.com/cppformat/cppformat/pull/112>`_).
|
||||
Thanks to `@CarterLi <https://github.com/CarterLi>`_.
|
||||
|
||||
* Improved compile-time errors when formatting wide into narrow strings
|
||||
(`#117 <https://github.com/cppformat/cppformat/issues/117>`_).
|
||||
|
||||
* Fixed ``BasicWriter::write`` without formatting arguments when C++11 support
|
||||
is disabled (`#109 <https://github.com/cppformat/cppformat/issues/109>`_).
|
||||
|
||||
* Fixed header-only build on OS X with GCC 4.9
|
||||
(`#124 <https://github.com/cppformat/cppformat/issues/124>`_).
|
||||
|
||||
* Fixed packaging issues (`#94 <https://github.com/cppformat/cppformat/issues/94>`_).
|
||||
|
||||
* Fixed warnings in GCC, MSVC and Xcode/Clang
|
||||
(`#95 <https://github.com/cppformat/cppformat/issues/95>`_,
|
||||
`#96 <https://github.com/cppformat/cppformat/issues/96>`_ and
|
||||
`#114 <https://github.com/cppformat/cppformat/pull/114>`_).
|
||||
|
||||
* Added `changelog <https://github.com/cppformat/cppformat/edit/master/ChangeLog.rst>`_
|
||||
(`#103 <https://github.com/cppformat/cppformat/issues/103>`_).
|
||||
|
||||
1.0.0 - 2015-02-05
|
||||
------------------
|
||||
|
||||
* Add support for a header-only configuration when ``FMT_HEADER_ONLY`` is
|
||||
defined before including ``format.h``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#define FMT_HEADER_ONLY
|
||||
#include "format.h"
|
||||
|
||||
* Compute string length in the constructor of ``BasicStringRef``
|
||||
instead of the ``size`` method
|
||||
(`#79 <https://github.com/cppformat/cppformat/issues/79>`_).
|
||||
This eliminates size computation for string literals on reasonable optimizing
|
||||
compilers.
|
||||
|
||||
* Fix formatting of types with overloaded ``operator <<`` for ``std::wostream``
|
||||
(`#86 <https://github.com/cppformat/cppformat/issues/86>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::format(L"The date is {0}", Date(2012, 12, 9));
|
||||
|
||||
* Fix linkage of tests on Arch Linux
|
||||
(`#89 <https://github.com/cppformat/cppformat/issues/89>`_).
|
||||
|
||||
* Allow precision specifier for non-float arguments
|
||||
(`#90 <https://github.com/cppformat/cppformat/issues/90>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::print("{:.3}\n", "Carpet"); // prints "Car"
|
||||
|
||||
* Fix build on Android NDK
|
||||
(`#93 <https://github.com/cppformat/cppformat/issues/93>`_)
|
||||
|
||||
* Improvements to documentation build procedure.
|
||||
|
||||
* Remove ``FMT_SHARED`` CMake variable in favor of standard `BUILD_SHARED_LIBS
|
||||
<http://www.cmake.org/cmake/help/v3.0/variable/BUILD_SHARED_LIBS.html>`_.
|
||||
|
||||
* Fix error handling in ``fmt::fprintf``.
|
||||
|
||||
* Fix a number of warnings.
|
||||
|
||||
0.12.0 - 2014-10-25
|
||||
-------------------
|
||||
|
||||
* [Breaking] Improved separation between formatting and buffer management.
|
||||
``Writer`` is now a base class that cannot be instantiated directly.
|
||||
The new ``MemoryWriter`` class implements the default buffer management
|
||||
with small allocations done on stack. So ``fmt::Writer`` should be replaced
|
||||
with ``fmt::MemoryWriter`` in variable declarations.
|
||||
|
||||
Old code:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::Writer w;
|
||||
|
||||
New code:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::MemoryWriter w;
|
||||
|
||||
If you pass ``fmt::Writer`` by reference, you can continue to do so:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
void f(fmt::Writer &w);
|
||||
|
||||
This doesn't affect the formatting API.
|
||||
|
||||
* Support for custom memory allocators
|
||||
(`#69 <https://github.com/cppformat/cppformat/issues/69>`_)
|
||||
|
||||
* Formatting functions now accept `signed char` and `unsigned char` strings as
|
||||
arguments (`#73 <https://github.com/cppformat/cppformat/issues/73>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
auto s = format("GLSL version: {}", glGetString(GL_VERSION));
|
||||
|
||||
* Reduced code bloat. According to the new `benchmark results
|
||||
<https://github.com/cppformat/cppformat#compile-time-and-code-bloat>`_,
|
||||
cppformat is close to ``printf`` and by the order of magnitude better than
|
||||
Boost Format in terms of compiled code size.
|
||||
|
||||
* Improved appearance of the documentation on mobile by using the `Sphinx
|
||||
Bootstrap theme <http://ryan-roemer.github.io/sphinx-bootstrap-theme/>`_:
|
||||
|
||||
.. |old| image:: https://cloud.githubusercontent.com/assets/576385/4792130/
|
||||
cd256436-5de3-11e4-9a62-c077d0c2b003.png
|
||||
|
||||
.. |new| image:: https://cloud.githubusercontent.com/assets/576385/4792131/
|
||||
cd29896c-5de3-11e4-8f59-cac952942bf0.png
|
||||
|
||||
+-------+-------+
|
||||
| Old | New |
|
||||
+-------+-------+
|
||||
| |old| | |new| |
|
||||
+-------+-------+
|
||||
|
||||
0.11.0 - 2014-08-21
|
||||
-------------------
|
||||
|
||||
* Safe printf implementation with a POSIX extension for positional arguments:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||
fmt::printf("%1$s, %3$d %2$s", weekday, month, day);
|
||||
|
||||
* Arguments of ``char`` type can now be formatted as integers
|
||||
(Issue `#55 <https://github.com/cppformat/cppformat/issues/55>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::format("0x{0:02X}", 'a');
|
||||
|
||||
* Deprecated parts of the API removed.
|
||||
|
||||
* The library is now built and tested on MinGW with Appveyor in addition to
|
||||
existing test platforms Linux/GCC, OS X/Clang, Windows/MSVC.
|
||||
|
||||
0.10.0 - 2014-07-01
|
||||
-------------------
|
||||
|
||||
**Improved API**
|
||||
|
||||
* All formatting methods are now implemented as variadic functions instead
|
||||
of using ``operator<<`` for feeding arbitrary arguments into a temporary
|
||||
formatter object. This works both with C++11 where variadic templates are
|
||||
used and with older standards where variadic functions are emulated by
|
||||
providing lightweight wrapper functions defined with the ``FMT_VARIADIC``
|
||||
macro. You can use this macro for defining your own portable variadic
|
||||
functions:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
void report_error(const char *format, const fmt::ArgList &args) {
|
||||
fmt::print("Error: {}");
|
||||
fmt::print(format, args);
|
||||
}
|
||||
FMT_VARIADIC(void, report_error, const char *)
|
||||
|
||||
report_error("file not found: {}", path);
|
||||
|
||||
Apart from a more natural syntax, this also improves performance as there
|
||||
is no need to construct temporary formatter objects and control arguments'
|
||||
lifetimes. Because the wrapper functions are very ligthweight, this doesn't
|
||||
cause code bloat even in pre-C++11 mode.
|
||||
|
||||
* Simplified common case of formatting an ``std::string``. Now it requires a
|
||||
single function call:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = format("The answer is {}.", 42);
|
||||
|
||||
Previously it required 2 function calls:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = str(Format("The answer is {}.") << 42);
|
||||
|
||||
Instead of unsafe ``c_str`` function, ``fmt::Writer`` should be used directly
|
||||
to bypass creation of ``std::string``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::Writer w;
|
||||
w.write("The answer is {}.", 42);
|
||||
w.c_str(); // returns a C string
|
||||
|
||||
This doesn't do dynamic memory allocation for small strings and is less error
|
||||
prone as the lifetime of the string is the same as for ``std::string::c_str``
|
||||
which is well understood (hopefully).
|
||||
|
||||
* Improved consistency in naming functions that are a part of the public API.
|
||||
Now all public functions are lowercase following the standard library
|
||||
conventions. Previously it was a combination of lowercase and
|
||||
CapitalizedWords.
|
||||
Issue `#50 <https://github.com/cppformat/cppformat/issues/50>`_.
|
||||
|
||||
* Old functions are marked as deprecated and will be removed in the next
|
||||
release.
|
||||
|
||||
**Other Changes**
|
||||
|
||||
* Experimental support for printf format specifications (work in progress):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::printf("The answer is %d.", 42);
|
||||
std::string s = fmt::sprintf("Look, a %s!", "string");
|
||||
|
||||
* Support for hexadecimal floating point format specifiers ``a`` and ``A``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
print("{:a}", -42.0); // Prints -0x1.5p+5
|
||||
print("{:A}", -42.0); // Prints -0X1.5P+5
|
||||
|
||||
* CMake option ``FMT_SHARED`` that specifies whether to build format as a
|
||||
shared library (off by default).
|
||||
|
||||
0.9.0 - 2014-05-13
|
||||
------------------
|
||||
|
||||
* More efficient implementation of variadic formatting functions.
|
||||
|
||||
* ``Writer::Format`` now has a variadic overload:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
Writer out;
|
||||
out.Format("Look, I'm {}!", "variadic");
|
||||
|
||||
* For efficiency and consistency with other overloads, variadic overload of
|
||||
the ``Format`` function now returns ``Writer`` instead of ``std::string``.
|
||||
Use the ``str`` function to convert it to ``std::string``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
std::string s = str(Format("Look, I'm {}!", "variadic"));
|
||||
|
||||
* Replaced formatter actions with output sinks: ``NoAction`` -> ``NullSink``,
|
||||
``Write`` -> ``FileSink``, ``ColorWriter`` -> ``ANSITerminalSink``.
|
||||
This improves naming consistency and shouldn't affect client code unless
|
||||
these classes are used directly which should be rarely needed.
|
||||
|
||||
* Added ``ThrowSystemError`` function that formats a message and throws
|
||||
``SystemError`` containing the formatted message and system-specific error
|
||||
description. For example, the following code
|
||||
|
||||
.. code:: c++
|
||||
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (!f)
|
||||
ThrowSystemError(errno, "Failed to open file '{}'") << filename;
|
||||
|
||||
will throw ``SystemError`` exception with description
|
||||
"Failed to open file '<filename>': No such file or directory" if file
|
||||
doesn't exist.
|
||||
|
||||
* Support for AppVeyor continuous integration platform.
|
||||
|
||||
* ``Format`` now throws ``SystemError`` in case of I/O errors.
|
||||
|
||||
* Improve test infrastructure. Print functions are now tested by redirecting
|
||||
the output to a pipe.
|
||||
|
||||
0.8.0 - 2014-04-14
|
||||
------------------
|
||||
|
||||
* Initial release
|
||||
22
dep/cppformat/LICENSE
Normal file
22
dep/cppformat/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2014 - 2015, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1175
dep/cppformat/format.cc
Normal file
1175
dep/cppformat/format.cc
Normal file
File diff suppressed because it is too large
Load Diff
2679
dep/cppformat/format.h
Normal file
2679
dep/cppformat/format.h
Normal file
File diff suppressed because it is too large
Load Diff
242
dep/cppformat/posix.cc
Normal file
242
dep/cppformat/posix.cc
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
A C++ interface to POSIX functions.
|
||||
|
||||
Copyright (c) 2014 - 2015, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Disable bogus MSVC warnings.
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "posix.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
|
||||
# define O_CREAT _O_CREAT
|
||||
# define O_TRUNC _O_TRUNC
|
||||
|
||||
#ifndef S_IRUSR
|
||||
# define S_IRUSR _S_IREAD
|
||||
#endif
|
||||
|
||||
#ifndef S_IWUSR
|
||||
# define S_IWUSR _S_IWRITE
|
||||
#endif
|
||||
|
||||
# ifdef __MINGW32__
|
||||
# define _SH_DENYNO 0x40
|
||||
# endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// Return type of read and write functions.
|
||||
typedef int RWResult;
|
||||
|
||||
// On Windows the count argument to read and write is unsigned, so convert
|
||||
// it from size_t preventing integer overflow.
|
||||
inline unsigned convert_rwcount(std::size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#else
|
||||
// Return type of read and write functions.
|
||||
typedef ssize_t RWResult;
|
||||
|
||||
inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
||||
#endif
|
||||
}
|
||||
|
||||
fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
|
||||
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
||||
fmt::report_system_error(errno, "cannot close file");
|
||||
}
|
||||
|
||||
fmt::BufferedFile::BufferedFile(fmt::StringRef filename, fmt::StringRef mode) {
|
||||
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
|
||||
if (!file_)
|
||||
throw SystemError(errno, "cannot open file {}", filename);
|
||||
}
|
||||
|
||||
void fmt::BufferedFile::close() {
|
||||
if (!file_)
|
||||
return;
|
||||
int result = FMT_SYSTEM(fclose(file_));
|
||||
file_ = 0;
|
||||
if (result != 0)
|
||||
throw SystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
int fmt::BufferedFile::fileno() const {
|
||||
int fd = FMT_POSIX_CALL(fileno(file_));
|
||||
if (fd == -1)
|
||||
throw SystemError(errno, "cannot get file descriptor");
|
||||
return fd;
|
||||
}
|
||||
|
||||
fmt::File::File(fmt::StringRef path, int oflag) {
|
||||
int mode = S_IRUSR | S_IWUSR;
|
||||
#ifdef _WIN32
|
||||
fd_ = -1;
|
||||
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
||||
#else
|
||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
|
||||
#endif
|
||||
if (fd_ == -1)
|
||||
throw SystemError(errno, "cannot open file {}", path);
|
||||
}
|
||||
|
||||
fmt::File::~File() FMT_NOEXCEPT {
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
||||
fmt::report_system_error(errno, "cannot close file");
|
||||
}
|
||||
|
||||
void fmt::File::close() {
|
||||
if (fd_ == -1)
|
||||
return;
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
int result = FMT_POSIX_CALL(close(fd_));
|
||||
fd_ = -1;
|
||||
if (result != 0)
|
||||
throw SystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
fmt::LongLong fmt::File::size() const {
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER filesize = {};
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
|
||||
if (!FMT_SYSTEM(GetFileSizeEx(handle, &filesize)))
|
||||
throw WindowsError(GetLastError(), "cannot get file size");
|
||||
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(filesize.QuadPart),
|
||||
"return type of File::size is not large enough");
|
||||
return filesize.QuadPart;
|
||||
#else
|
||||
typedef struct stat Stat;
|
||||
Stat file_stat = Stat();
|
||||
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
|
||||
throw SystemError(errno, "cannot get file attributes");
|
||||
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
|
||||
"return type of File::size is not large enough");
|
||||
return file_stat.st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t fmt::File::read(void *buffer, std::size_t count) {
|
||||
RWResult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0)
|
||||
throw SystemError(errno, "cannot read from file");
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t fmt::File::write(const void *buffer, std::size_t count) {
|
||||
RWResult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0)
|
||||
throw SystemError(errno, "cannot write to file");
|
||||
return result;
|
||||
}
|
||||
|
||||
fmt::File fmt::File::dup(int fd) {
|
||||
// Don't retry as dup doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||
if (new_fd == -1)
|
||||
throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
|
||||
return File(new_fd);
|
||||
}
|
||||
|
||||
void fmt::File::dup2(int fd) {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1) {
|
||||
throw SystemError(errno,
|
||||
"cannot duplicate file descriptor {} to {}", fd_, fd);
|
||||
}
|
||||
}
|
||||
|
||||
void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1)
|
||||
ec = ErrorCode(errno);
|
||||
}
|
||||
|
||||
void fmt::File::pipe(File &read_end, File &write_end) {
|
||||
// Close the descriptors first to make sure that assignments don't throw
|
||||
// and there are no leaks.
|
||||
read_end.close();
|
||||
write_end.close();
|
||||
int fds[2] = {};
|
||||
#ifdef _WIN32
|
||||
// Make the default pipe capacity same as on Linux 2.6.11+.
|
||||
enum { DEFAULT_CAPACITY = 65536 };
|
||||
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
|
||||
#else
|
||||
// Don't retry as the pipe function doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
|
||||
int result = FMT_POSIX_CALL(pipe(fds));
|
||||
#endif
|
||||
if (result != 0)
|
||||
throw SystemError(errno, "cannot create pipe");
|
||||
// The following assignments don't throw because read_fd and write_fd
|
||||
// are closed.
|
||||
read_end = File(fds[0]);
|
||||
write_end = File(fds[1]);
|
||||
}
|
||||
|
||||
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||
if (!f)
|
||||
throw SystemError(errno, "cannot associate stream with file descriptor");
|
||||
BufferedFile file(f);
|
||||
fd_ = -1;
|
||||
return file;
|
||||
}
|
||||
|
||||
long fmt::getpagesize() {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwPageSize;
|
||||
#else
|
||||
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
|
||||
if (size < 0)
|
||||
throw SystemError(errno, "cannot get memory page size");
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
337
dep/cppformat/posix.h
Normal file
337
dep/cppformat/posix.h
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
A C++ interface to POSIX functions.
|
||||
|
||||
Copyright (c) 2014 - 2015, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FMT_POSIX_H_
|
||||
#define FMT_POSIX_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h> // for O_RDONLY
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#ifdef FMT_INCLUDE_POSIX_TEST
|
||||
# include "test/posix-test.h"
|
||||
#endif
|
||||
|
||||
#ifndef FMT_POSIX
|
||||
# ifdef _WIN32
|
||||
// Fix warnings about deprecated symbols.
|
||||
# define FMT_POSIX(call) _##call
|
||||
# else
|
||||
# define FMT_POSIX(call) call
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
|
||||
#ifdef FMT_SYSTEM
|
||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
||||
#else
|
||||
# define FMT_SYSTEM(call) call
|
||||
# ifdef _WIN32
|
||||
// Fix warnings about deprecated symbols.
|
||||
# define FMT_POSIX_CALL(call) ::_##call
|
||||
# else
|
||||
# define FMT_POSIX_CALL(call) ::call
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FMT_GCC_VERSION >= 407
|
||||
# define FMT_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define FMT_UNUSED
|
||||
#endif
|
||||
|
||||
#if FMT_USE_STATIC_ASSERT || FMT_HAS_CPP_ATTRIBUTE(cxx_static_assert) || \
|
||||
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
|
||||
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
|
||||
#else
|
||||
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
|
||||
# define FMT_STATIC_ASSERT(cond, message) \
|
||||
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
||||
#endif
|
||||
|
||||
// Retries the expression while it evaluates to error_result and errno
|
||||
// equals to EINTR.
|
||||
#ifndef _WIN32
|
||||
# define FMT_RETRY_VAL(result, expression, error_result) \
|
||||
do { \
|
||||
result = (expression); \
|
||||
} while (result == error_result && errno == EINTR)
|
||||
#else
|
||||
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
|
||||
#endif
|
||||
|
||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
||||
|
||||
namespace fmt {
|
||||
|
||||
// An error code.
|
||||
class ErrorCode {
|
||||
private:
|
||||
int value_;
|
||||
|
||||
public:
|
||||
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
|
||||
|
||||
int get() const FMT_NOEXCEPT { return value_; }
|
||||
};
|
||||
|
||||
// A buffered file.
|
||||
class BufferedFile {
|
||||
private:
|
||||
FILE *file_;
|
||||
|
||||
friend class File;
|
||||
|
||||
explicit BufferedFile(FILE *f) : file_(f) {}
|
||||
|
||||
public:
|
||||
// Constructs a BufferedFile object which doesn't represent any file.
|
||||
BufferedFile() FMT_NOEXCEPT : file_(0) {}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
~BufferedFile() FMT_NOEXCEPT;
|
||||
|
||||
#if !FMT_USE_RVALUE_REFERENCES
|
||||
// Emulate a move constructor and a move assignment operator if rvalue
|
||||
// references are not supported.
|
||||
|
||||
private:
|
||||
// A proxy object to emulate a move constructor.
|
||||
// It is private to make it impossible call operator Proxy directly.
|
||||
struct Proxy {
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
public:
|
||||
// A "move constructor" for moving from a temporary.
|
||||
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
|
||||
|
||||
// A "move constructor" for for moving from an lvalue.
|
||||
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
|
||||
f.file_ = 0;
|
||||
}
|
||||
|
||||
// A "move assignment operator" for moving from a temporary.
|
||||
BufferedFile &operator=(Proxy p) {
|
||||
close();
|
||||
file_ = p.file;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// A "move assignment operator" for moving from an lvalue.
|
||||
BufferedFile &operator=(BufferedFile &other) {
|
||||
close();
|
||||
file_ = other.file_;
|
||||
other.file_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a proxy object for moving from a temporary:
|
||||
// BufferedFile file = BufferedFile(...);
|
||||
operator Proxy() FMT_NOEXCEPT {
|
||||
Proxy p = {file_};
|
||||
file_ = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
#else
|
||||
private:
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
|
||||
|
||||
public:
|
||||
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
|
||||
other.file_ = 0;
|
||||
}
|
||||
|
||||
BufferedFile& operator=(BufferedFile &&other) {
|
||||
close();
|
||||
file_ = other.file_;
|
||||
other.file_ = 0;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Opens a file.
|
||||
BufferedFile(fmt::StringRef filename, fmt::StringRef mode);
|
||||
|
||||
// Closes the file.
|
||||
void close();
|
||||
|
||||
// Returns the pointer to a FILE object representing this file.
|
||||
FILE *get() const FMT_NOEXCEPT { return file_; }
|
||||
|
||||
int fileno() const;
|
||||
|
||||
void print(fmt::StringRef format_str, const ArgList &args) {
|
||||
fmt::print(file_, format_str, args);
|
||||
}
|
||||
FMT_VARIADIC(void, print, fmt::StringRef)
|
||||
};
|
||||
|
||||
// A file. Closed file is represented by a File object with descriptor -1.
|
||||
// Methods that are not declared with FMT_NOEXCEPT may throw
|
||||
// fmt::SystemError in case of failure. Note that some errors such as
|
||||
// closing the file multiple times will cause a crash on Windows rather
|
||||
// than an exception. You can get standard behavior by overriding the
|
||||
// invalid parameter handler with _set_invalid_parameter_handler.
|
||||
class File {
|
||||
private:
|
||||
int fd_; // File descriptor.
|
||||
|
||||
// Constructs a File object with a given descriptor.
|
||||
explicit File(int fd) : fd_(fd) {}
|
||||
|
||||
public:
|
||||
// Possible values for the oflag argument to the constructor.
|
||||
enum {
|
||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
||||
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
|
||||
};
|
||||
|
||||
// Constructs a File object which doesn't represent any file.
|
||||
File() FMT_NOEXCEPT : fd_(-1) {}
|
||||
|
||||
// Opens a file and constructs a File object representing this file.
|
||||
File(fmt::StringRef path, int oflag);
|
||||
|
||||
#if !FMT_USE_RVALUE_REFERENCES
|
||||
// Emulate a move constructor and a move assignment operator if rvalue
|
||||
// references are not supported.
|
||||
|
||||
private:
|
||||
// A proxy object to emulate a move constructor.
|
||||
// It is private to make it impossible call operator Proxy directly.
|
||||
struct Proxy {
|
||||
int fd;
|
||||
};
|
||||
|
||||
public:
|
||||
// A "move constructor" for moving from a temporary.
|
||||
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
|
||||
|
||||
// A "move constructor" for for moving from an lvalue.
|
||||
File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
|
||||
other.fd_ = -1;
|
||||
}
|
||||
|
||||
// A "move assignment operator" for moving from a temporary.
|
||||
File &operator=(Proxy p) {
|
||||
close();
|
||||
fd_ = p.fd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// A "move assignment operator" for moving from an lvalue.
|
||||
File &operator=(File &other) {
|
||||
close();
|
||||
fd_ = other.fd_;
|
||||
other.fd_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a proxy object for moving from a temporary:
|
||||
// File file = File(...);
|
||||
operator Proxy() FMT_NOEXCEPT {
|
||||
Proxy p = {fd_};
|
||||
fd_ = -1;
|
||||
return p;
|
||||
}
|
||||
|
||||
#else
|
||||
private:
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(File);
|
||||
|
||||
public:
|
||||
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
|
||||
other.fd_ = -1;
|
||||
}
|
||||
|
||||
File& operator=(File &&other) {
|
||||
close();
|
||||
fd_ = other.fd_;
|
||||
other.fd_ = -1;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
~File() FMT_NOEXCEPT;
|
||||
|
||||
// Returns the file descriptor.
|
||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
||||
|
||||
// Closes the file.
|
||||
void close();
|
||||
|
||||
// Returns the file size.
|
||||
fmt::LongLong size() const;
|
||||
|
||||
// Attempts to read count bytes from the file into the specified buffer.
|
||||
std::size_t read(void *buffer, std::size_t count);
|
||||
|
||||
// Attempts to write count bytes from the specified buffer to the file.
|
||||
std::size_t write(const void *buffer, std::size_t count);
|
||||
|
||||
// Duplicates a file descriptor with the dup function and returns
|
||||
// the duplicate as a file object.
|
||||
static File dup(int fd);
|
||||
|
||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||
// necessary.
|
||||
void dup2(int fd);
|
||||
|
||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||
// necessary.
|
||||
void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
|
||||
|
||||
// Creates a pipe setting up read_end and write_end file objects for reading
|
||||
// and writing respectively.
|
||||
static void pipe(File &read_end, File &write_end);
|
||||
|
||||
// Creates a BufferedFile object associated with this file and detaches
|
||||
// this File object from the file.
|
||||
BufferedFile fdopen(const char *mode);
|
||||
};
|
||||
|
||||
// Returns the memory page size.
|
||||
long getpagesize();
|
||||
} // namespace fmt
|
||||
|
||||
#if !FMT_USE_RVALUE_REFERENCES
|
||||
namespace std {
|
||||
// For compatibility with C++98.
|
||||
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
|
||||
inline fmt::File &move(fmt::File &f) { return f; }
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // FMT_POSIX_H_
|
||||
Reference in New Issue
Block a user