mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
Merge pull request #11123 from Pokechu22/fmt-9.1.0
Externals: Update fmt to 9.1.0
This commit is contained in:
commit
d6437b7e46
8
Externals/fmt/CMakeLists.txt
vendored
8
Externals/fmt/CMakeLists.txt
vendored
@ -218,7 +218,7 @@ endfunction()
|
||||
|
||||
# Define the fmt library, its includes and the needed defines.
|
||||
add_headers(FMT_HEADERS args.h chrono.h color.h compile.h core.h format.h
|
||||
format-inl.h locale.h os.h ostream.h printf.h ranges.h
|
||||
format-inl.h os.h ostream.h printf.h ranges.h std.h
|
||||
xchar.h)
|
||||
if (FMT_MODULE)
|
||||
set(FMT_SOURCES src/fmt.cc)
|
||||
@ -263,12 +263,6 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
endif ()
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND
|
||||
NOT EMSCRIPTEN)
|
||||
# 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 ()
|
||||
if (FMT_SAFE_DURATION_CAST)
|
||||
|
519
Externals/fmt/ChangeLog.rst
vendored
519
Externals/fmt/ChangeLog.rst
vendored
@ -1,3 +1,515 @@
|
||||
9.1.0 - 2022-08-27
|
||||
------------------
|
||||
|
||||
* ``fmt::formatted_size`` now works at compile time
|
||||
(`#3026 <https://github.com/fmtlib/fmt/pull/3026>`_). For example
|
||||
(`godbolt <https://godbolt.org/z/1MW5rMdf8>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/compile.h>
|
||||
|
||||
int main() {
|
||||
using namespace fmt::literals;
|
||||
constexpr size_t n = fmt::formatted_size("{}"_cf, 42);
|
||||
fmt::print("{}\n", n); // prints 2
|
||||
}
|
||||
|
||||
Thanks `@marksantaniello (Mark Santaniello)
|
||||
<https://github.com/marksantaniello>`_.
|
||||
|
||||
* Fixed handling of invalid UTF-8
|
||||
(`#3038 <https://github.com/fmtlib/fmt/pull/3038>`_,
|
||||
`#3044 <https://github.com/fmtlib/fmt/pull/3044>`_,
|
||||
`#3056 <https://github.com/fmtlib/fmt/pull/3056>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_ and
|
||||
`@skeeto (Christopher Wellons) <https://github.com/skeeto>`_.
|
||||
|
||||
* Improved Unicode support in ``ostream`` overloads of ``print``
|
||||
(`#2994 <https://github.com/fmtlib/fmt/pull/2994>`_,
|
||||
`#3001 <https://github.com/fmtlib/fmt/pull/3001>`_,
|
||||
`#3025 <https://github.com/fmtlib/fmt/pull/3025>`_).
|
||||
Thanks `@dimztimz (Dimitrij Mijoski) <https://github.com/dimztimz>`_.
|
||||
|
||||
* Fixed handling of the sign specifier in localized formatting on systems with
|
||||
32-bit ``wchar_t`` (`#3041 <https://github.com/fmtlib/fmt/issues/3041>`_).
|
||||
|
||||
* Added support for wide streams to ``fmt::streamed``
|
||||
(`#2994 <https://github.com/fmtlib/fmt/pull/2994>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Added the ``n`` specifier that disables the output of delimiters when
|
||||
formatting ranges (`#2981 <https://github.com/fmtlib/fmt/pull/2981>`_,
|
||||
`#2983 <https://github.com/fmtlib/fmt/pull/2983>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/roKqGdj8c>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/ranges.h>
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
auto v = std::vector{1, 2, 3};
|
||||
fmt::print("{:n}\n", v); // prints 1, 2, 3
|
||||
}
|
||||
|
||||
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
|
||||
|
||||
* Worked around problematic ``std::string_view`` constructors introduced in
|
||||
C++23 (`#3030 <https://github.com/fmtlib/fmt/issues/3030>`_,
|
||||
`#3050 <https://github.com/fmtlib/fmt/issues/3050>`_).
|
||||
Thanks `@strega-nil-ms (nicole mazzuca) <https://github.com/strega-nil-ms>`_.
|
||||
|
||||
* Improve handling (exclusion) of recursive ranges
|
||||
(`#2968 <https://github.com/fmtlib/fmt/issues/2968>`_,
|
||||
`#2974 <https://github.com/fmtlib/fmt/pull/2974>`_).
|
||||
Thanks `@Dani-Hub (Daniel Krügler) <https://github.com/Dani-Hub>`_.
|
||||
|
||||
* Improved error reporting in format string compilation
|
||||
(`#3055 <https://github.com/fmtlib/fmt/issues/3055>`_).
|
||||
|
||||
* Improved the implementation of
|
||||
`Dragonbox <https://github.com/jk-jeon/dragonbox>`_, the algorithm used for
|
||||
the default floating-point formatting
|
||||
(`#2984 <https://github.com/fmtlib/fmt/pull/2984>`_).
|
||||
Thanks `@jk-jeon (Junekey Jeon) <https://github.com/jk-jeon>`_.
|
||||
|
||||
* Fixed issues with floating-point formatting on exotic platforms.
|
||||
|
||||
* Improved the implementation of chrono formatting
|
||||
(`#3010 <https://github.com/fmtlib/fmt/pull/3010>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Improved documentation
|
||||
(`#2966 <https://github.com/fmtlib/fmt/pull/2966>`_,
|
||||
`#3009 <https://github.com/fmtlib/fmt/pull/3009>`_,
|
||||
`#3020 <https://github.com/fmtlib/fmt/issues/3020>`_,
|
||||
`#3037 <https://github.com/fmtlib/fmt/pull/3037>`_).
|
||||
Thanks `@mwinterb <https://github.com/mwinterb>`_,
|
||||
`@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_
|
||||
and `@remiburtin (Rémi Burtin) <https://github.com/remiburtin>`_.
|
||||
|
||||
* Improved build configuration
|
||||
(`#2991 <https://github.com/fmtlib/fmt/pull/2991>`_,
|
||||
`#2995 <https://github.com/fmtlib/fmt/pull/2995>`_,
|
||||
`#3004 <https://github.com/fmtlib/fmt/issues/3004>`_,
|
||||
`#3007 <https://github.com/fmtlib/fmt/pull/3007>`_,
|
||||
`#3040 <https://github.com/fmtlib/fmt/pull/3040>`_).
|
||||
Thanks `@dimztimz (Dimitrij Mijoski) <https://github.com/dimztimz>`_ and
|
||||
`@hwhsu1231 (Haowei Hsu) <https://github.com/hwhsu1231>`_.
|
||||
|
||||
* Fixed various warnings and compilation issues
|
||||
(`#2969 <https://github.com/fmtlib/fmt/issues/2969>`_,
|
||||
`#2971 <https://github.com/fmtlib/fmt/pull/2971>`_,
|
||||
`#2975 <https://github.com/fmtlib/fmt/issues/2975>`_,
|
||||
`#2982 <https://github.com/fmtlib/fmt/pull/2982>`_,
|
||||
`#2985 <https://github.com/fmtlib/fmt/pull/2985>`_,
|
||||
`#2988 <https://github.com/fmtlib/fmt/issues/2988>`_,
|
||||
`#3000 <https://github.com/fmtlib/fmt/issues/3000>`_,
|
||||
`#3006 <https://github.com/fmtlib/fmt/issues/3006>`_,
|
||||
`#3014 <https://github.com/fmtlib/fmt/issues/3014>`_,
|
||||
`#3015 <https://github.com/fmtlib/fmt/issues/3015>`_,
|
||||
`#3021 <https://github.com/fmtlib/fmt/pull/3021>`_,
|
||||
`#3023 <https://github.com/fmtlib/fmt/issues/3023>`_,
|
||||
`#3024 <https://github.com/fmtlib/fmt/pull/3024>`_,
|
||||
`#3029 <https://github.com/fmtlib/fmt/pull/3029>`_,
|
||||
`#3043 <https://github.com/fmtlib/fmt/pull/3043>`_,
|
||||
`#3052 <https://github.com/fmtlib/fmt/issues/3052>`_,
|
||||
`#3053 <https://github.com/fmtlib/fmt/pull/3053>`_,
|
||||
`#3054 <https://github.com/fmtlib/fmt/pull/3054>`_).
|
||||
Thanks `@h-friederich (Hannes Friederich) <https://github.com/h-friederich>`_,
|
||||
`@dimztimz (Dimitrij Mijoski) <https://github.com/dimztimz>`_,
|
||||
`@olupton (Olli Lupton) <https://github.com/olupton>`_,
|
||||
`@bernhardmgruber (Bernhard Manfred Gruber)
|
||||
<https://github.com/bernhardmgruber>`_,
|
||||
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
9.0.0 - 2022-07-04
|
||||
------------------
|
||||
|
||||
* Switched to the internal floating point formatter for all decimal presentation
|
||||
formats. In particular this results in consistent rounding on all platforms
|
||||
and removing the ``s[n]printf`` fallback for decimal FP formatting.
|
||||
|
||||
* Compile-time floating point formatting no longer requires the header-only
|
||||
mode. For example (`godbolt <https://godbolt.org/z/G37PTeG3b>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <array>
|
||||
#include <fmt/compile.h>
|
||||
|
||||
consteval auto compile_time_dtoa(double value) -> std::array<char, 10> {
|
||||
auto result = std::array<char, 10>();
|
||||
fmt::format_to(result.data(), FMT_COMPILE("{}"), value);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr auto answer = compile_time_dtoa(0.42);
|
||||
|
||||
works with the default settings.
|
||||
|
||||
* Improved the implementation of
|
||||
`Dragonbox <https://github.com/jk-jeon/dragonbox>`_, the algorithm used for
|
||||
the default floating-point formatting
|
||||
(`#2713 <https://github.com/fmtlib/fmt/pull/2713>`_,
|
||||
`#2750 <https://github.com/fmtlib/fmt/pull/2750>`_).
|
||||
Thanks `@jk-jeon (Junekey Jeon) <https://github.com/jk-jeon>`_.
|
||||
|
||||
* Made ``fmt::to_string`` work with ``__float128``. This uses the internal
|
||||
FP formatter and works even on system without ``__float128`` support in
|
||||
``[s]printf``.
|
||||
|
||||
* Disabled automatic ``std::ostream`` insertion operator (``operator<<``)
|
||||
discovery when ``fmt/ostream.h`` is included to prevent ODR violations.
|
||||
You can get the old behavior by defining ``FMT_DEPRECATED_OSTREAM`` but this
|
||||
will be removed in the next major release. Use ``fmt::streamed`` or
|
||||
``fmt::ostream_formatter`` to enable formatting via ``std::ostream`` instead.
|
||||
|
||||
* Added ``fmt::ostream_formatter`` that can be used to write ``formatter``
|
||||
specializations that perform formatting via ``std::ostream``.
|
||||
For example (`godbolt <https://godbolt.org/z/5sEc5qMsf>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
struct date {
|
||||
int year, month, day;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const date& d) {
|
||||
return os << d.year << '-' << d.month << '-' << d.day;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct fmt::formatter<date> : ostream_formatter {};
|
||||
|
||||
std::string s = fmt::format("The date is {}", date{2012, 12, 9});
|
||||
// s == "The date is 2012-12-9"
|
||||
|
||||
* Added the ``fmt::streamed`` function that takes an object and formats it
|
||||
via ``std::ostream``.
|
||||
For example (`godbolt <https://godbolt.org/z/5G3346G1f>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <thread>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("Current thread id: {}\n",
|
||||
fmt::streamed(std::this_thread::get_id()));
|
||||
}
|
||||
|
||||
Note that ``fmt/std.h`` provides a ``formatter`` specialization for
|
||||
``std::thread::id`` so you don't need to format it via ``std::ostream``.
|
||||
|
||||
* Deprecated implicit conversions of unscoped enums to integers for consistency
|
||||
with scoped enums.
|
||||
|
||||
* Added an argument-dependent lookup based ``format_as`` extension API to
|
||||
simplify formatting of enums.
|
||||
|
||||
* Added experimental ``std::variant`` formatting support
|
||||
(`#2941 <https://github.com/fmtlib/fmt/pull/2941>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/KG9z6cq68>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <variant>
|
||||
#include <fmt/std.h>
|
||||
|
||||
int main() {
|
||||
auto v = std::variant<int, std::string>(42);
|
||||
fmt::print("{}\n", v);
|
||||
}
|
||||
|
||||
prints::
|
||||
|
||||
variant(42)
|
||||
|
||||
Thanks `@jehelset <https://github.com/jehelset>`_.
|
||||
|
||||
* Added experimental ``std::filesystem::path`` formatting support
|
||||
(`#2865 <https://github.com/fmtlib/fmt/issues/2865>`_,
|
||||
`#2902 <https://github.com/fmtlib/fmt/pull/2902>`_,
|
||||
`#2917 <https://github.com/fmtlib/fmt/issues/2917>`_,
|
||||
`#2918 <https://github.com/fmtlib/fmt/pull/2918>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/o44dMexEb>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <filesystem>
|
||||
#include <fmt/std.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("There is no place like {}.", std::filesystem::path("/home"));
|
||||
}
|
||||
|
||||
prints::
|
||||
|
||||
There is no place like "/home".
|
||||
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Added a ``std::thread::id`` formatter to ``fmt/std.h``.
|
||||
For example (`godbolt <https://godbolt.org/z/j1azbYf3E>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <thread>
|
||||
#include <fmt/std.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("Current thread id: {}\n", std::this_thread::get_id());
|
||||
}
|
||||
|
||||
* Added ``fmt::styled`` that applies a text style to an individual argument
|
||||
(`#2793 <https://github.com/fmtlib/fmt/pull/2793>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/vWGW7v5M6>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <fmt/color.h>
|
||||
|
||||
int main() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
fmt::print(
|
||||
"[{}] {}: {}\n",
|
||||
fmt::styled(now, fmt::emphasis::bold),
|
||||
fmt::styled("error", fg(fmt::color::red)),
|
||||
"something went wrong");
|
||||
}
|
||||
|
||||
prints
|
||||
|
||||
.. image:: https://user-images.githubusercontent.com/576385/
|
||||
175071215-12809244-dab0-4005-96d8-7cd911c964d5.png
|
||||
|
||||
Thanks `@rbrugo (Riccardo Brugo) <https://github.com/rbrugo>`_.
|
||||
|
||||
* Made ``fmt::print`` overload for text styles correctly handle UTF-8
|
||||
(`#2681 <https://github.com/fmtlib/fmt/issues/2681>`_,
|
||||
`#2701 <https://github.com/fmtlib/fmt/pull/2701>`_).
|
||||
Thanks `@AlexGuteniev (Alex Guteniev) <https://github.com/AlexGuteniev>`_.
|
||||
|
||||
* Fixed Unicode handling when writing to an ostream.
|
||||
|
||||
* Added support for nested specifiers to range formatting
|
||||
(`#2673 <https://github.com/fmtlib/fmt/pull/2673>`_).
|
||||
For example (`godbolt <https://godbolt.org/z/xd3Gj38cf>`__):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <vector>
|
||||
#include <fmt/ranges.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("{::#x}\n", std::vector{10, 20, 30});
|
||||
}
|
||||
|
||||
prints ``[0xa, 0x14, 0x1e]``.
|
||||
|
||||
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
|
||||
|
||||
* Implemented escaping of wide strings in ranges
|
||||
(`#2904 <https://github.com/fmtlib/fmt/pull/2904>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Added support for ranges with ``begin`` / ``end`` found via the
|
||||
argument-dependent lookup
|
||||
(`#2807 <https://github.com/fmtlib/fmt/pull/2807>`_).
|
||||
Thanks `@rbrugo (Riccardo Brugo) <https://github.com/rbrugo>`_.
|
||||
|
||||
* Fixed formatting of certain kinds of ranges of ranges
|
||||
(`#2787 <https://github.com/fmtlib/fmt/pull/2787>`_).
|
||||
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
|
||||
|
||||
* Fixed handling of maps with element types other than ``std::pair``
|
||||
(`#2944 <https://github.com/fmtlib/fmt/pull/2944>`_).
|
||||
Thanks `@BrukerJWD (Jonathan W) <https://github.com/BrukerJWD>`_.
|
||||
|
||||
* Made tuple formatter enabled only if elements are formattable
|
||||
(`#2939 <https://github.com/fmtlib/fmt/issues/2939>`_,
|
||||
`#2940 <https://github.com/fmtlib/fmt/pull/2940>`_).
|
||||
Thanks `@jehelset <https://github.com/jehelset>`_.
|
||||
|
||||
* Made ``fmt::join`` compatible with format string compilation
|
||||
(`#2719 <https://github.com/fmtlib/fmt/issues/2719>`_,
|
||||
`#2720 <https://github.com/fmtlib/fmt/pull/2720>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Made compile-time checks work with named arguments of custom types and
|
||||
``std::ostream`` ``print`` overloads
|
||||
(`#2816 <https://github.com/fmtlib/fmt/issues/2816>`_,
|
||||
`#2817 <https://github.com/fmtlib/fmt/issues/2817>`_,
|
||||
`#2819 <https://github.com/fmtlib/fmt/pull/2819>`_).
|
||||
Thanks `@timsong-cpp <https://github.com/timsong-cpp>`_.
|
||||
|
||||
* Removed ``make_args_checked`` because it is no longer needed for compile-time
|
||||
checks (`#2760 <https://github.com/fmtlib/fmt/pull/2760>`_).
|
||||
Thanks `@phprus (Vladislav Shchapov) <https://github.com/phprus>`_.
|
||||
|
||||
* Removed the following deprecated APIs: ``_format``, ``arg_join``,
|
||||
the ``format_to`` overload that takes a memory buffer,
|
||||
``[v]fprintf`` that takes an ``ostream``.
|
||||
|
||||
* Removed the deprecated implicit conversion of ``[const] signed char*`` and
|
||||
``[const] unsigned char*`` to C strings.
|
||||
|
||||
* Removed the deprecated ``fmt/locale.h``.
|
||||
|
||||
* Replaced the deprecated ``fileno()`` with ``descriptor()`` in
|
||||
``buffered_file``.
|
||||
|
||||
* Moved ``to_string_view`` to the ``detail`` namespace since it's an
|
||||
implementation detail.
|
||||
|
||||
* Made access mode of a created file consistent with ``fopen`` by setting
|
||||
``S_IWGRP`` and ``S_IWOTH``
|
||||
(`#2733 <https://github.com/fmtlib/fmt/pull/2733>`_).
|
||||
Thanks `@arogge (Andreas Rogge) <https://github.com/arogge>`_.
|
||||
|
||||
* Removed a redundant buffer resize when formatting to ``std::ostream``
|
||||
(`#2842 <https://github.com/fmtlib/fmt/issues/2842>`_,
|
||||
`#2843 <https://github.com/fmtlib/fmt/pull/2843>`_).
|
||||
Thanks `@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_.
|
||||
|
||||
* Made precision computation for strings consistent with width
|
||||
(`#2888 <https://github.com/fmtlib/fmt/issues/2888>`_).
|
||||
|
||||
* Fixed handling of locale separators in floating point formatting
|
||||
(`#2830 <https://github.com/fmtlib/fmt/issues/2830>`_).
|
||||
|
||||
* Made sign specifiers work with ``__int128_t``
|
||||
(`#2773 <https://github.com/fmtlib/fmt/issues/2773>`_).
|
||||
|
||||
* Improved support for systems such as CHERI with extra data stored in pointers
|
||||
(`#2932 <https://github.com/fmtlib/fmt/pull/2932>`_).
|
||||
Thanks `@davidchisnall (David Chisnall) <https://github.com/davidchisnall>`_.
|
||||
|
||||
* Improved documentation
|
||||
(`#2706 <https://github.com/fmtlib/fmt/pull/2706>`_,
|
||||
`#2712 <https://github.com/fmtlib/fmt/pull/2712>`_,
|
||||
`#2789 <https://github.com/fmtlib/fmt/pull/2789>`_,
|
||||
`#2803 <https://github.com/fmtlib/fmt/pull/2803>`_,
|
||||
`#2805 <https://github.com/fmtlib/fmt/pull/2805>`_,
|
||||
`#2815 <https://github.com/fmtlib/fmt/pull/2815>`_,
|
||||
`#2924 <https://github.com/fmtlib/fmt/pull/2924>`_).
|
||||
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_,
|
||||
`@Pokechu22 <https://github.com/Pokechu22>`_,
|
||||
`@setoye (Alta) <https://github.com/setoye>`_,
|
||||
`@rtobar <https://github.com/rtobar>`_,
|
||||
`@rbrugo (Riccardo Brugo) <https://github.com/rbrugo>`_,
|
||||
`@anoonD (cre) <https://github.com/anoonD>`_,
|
||||
`@leha-bot (Alex) <https://github.com/leha-bot>`_.
|
||||
|
||||
* Improved build configuration
|
||||
(`#2766 <https://github.com/fmtlib/fmt/pull/2766>`_,
|
||||
`#2772 <https://github.com/fmtlib/fmt/pull/2772>`_,
|
||||
`#2836 <https://github.com/fmtlib/fmt/pull/2836>`_,
|
||||
`#2852 <https://github.com/fmtlib/fmt/pull/2852>`_,
|
||||
`#2907 <https://github.com/fmtlib/fmt/pull/2907>`_,
|
||||
`#2913 <https://github.com/fmtlib/fmt/pull/2913>`_,
|
||||
`#2914 <https://github.com/fmtlib/fmt/pull/2914>`_).
|
||||
Thanks `@kambala-decapitator (Andrey Filipenkov)
|
||||
<https://github.com/kambala-decapitator>`_,
|
||||
`@mattiasljungstrom (Mattias Ljungström)
|
||||
<https://github.com/mattiasljungstrom>`_,
|
||||
`@kieselnb (Nick Kiesel) <https://github.com/kieselnb>`_,
|
||||
`@nathannaveen <https://github.com/nathannaveen>`_,
|
||||
`@Vertexwahn <https://github.com/Vertexwahn>`_.
|
||||
|
||||
* Fixed various warnings and compilation issues
|
||||
(`#2408 <https://github.com/fmtlib/fmt/issues/2408>`_,
|
||||
`#2507 <https://github.com/fmtlib/fmt/issues/2507>`_,
|
||||
`#2697 <https://github.com/fmtlib/fmt/issues/2697>`_,
|
||||
`#2715 <https://github.com/fmtlib/fmt/issues/2715>`_,
|
||||
`#2717 <https://github.com/fmtlib/fmt/issues/2717>`_,
|
||||
`#2722 <https://github.com/fmtlib/fmt/pull/2722>`_,
|
||||
`#2724 <https://github.com/fmtlib/fmt/pull/2724>`_,
|
||||
`#2725 <https://github.com/fmtlib/fmt/pull/2725>`_,
|
||||
`#2726 <https://github.com/fmtlib/fmt/issues/2726>`_,
|
||||
`#2728 <https://github.com/fmtlib/fmt/pull/2728>`_,
|
||||
`#2732 <https://github.com/fmtlib/fmt/pull/2732>`_,
|
||||
`#2738 <https://github.com/fmtlib/fmt/issues/2738>`_,
|
||||
`#2742 <https://github.com/fmtlib/fmt/pull/2742>`_,
|
||||
`#2744 <https://github.com/fmtlib/fmt/issues/2744>`_,
|
||||
`#2745 <https://github.com/fmtlib/fmt/issues/2745>`_,
|
||||
`#2746 <https://github.com/fmtlib/fmt/issues/2746>`_,
|
||||
`#2754 <https://github.com/fmtlib/fmt/issues/2754>`_,
|
||||
`#2755 <https://github.com/fmtlib/fmt/pull/2755>`_,
|
||||
`#2757 <https://github.com/fmtlib/fmt/issues/2757>`_,
|
||||
`#2758 <https://github.com/fmtlib/fmt/pull/2758>`_,
|
||||
`#2761 <https://github.com/fmtlib/fmt/issues/2761>`_,
|
||||
`#2762 <https://github.com/fmtlib/fmt/pull/2762>`_,
|
||||
`#2763 <https://github.com/fmtlib/fmt/issues/2763>`_,
|
||||
`#2765 <https://github.com/fmtlib/fmt/pull/2765>`_,
|
||||
`#2769 <https://github.com/fmtlib/fmt/issues/2769>`_,
|
||||
`#2770 <https://github.com/fmtlib/fmt/pull/2770>`_,
|
||||
`#2771 <https://github.com/fmtlib/fmt/issues/2771>`_,
|
||||
`#2777 <https://github.com/fmtlib/fmt/issues/2777>`_,
|
||||
`#2779 <https://github.com/fmtlib/fmt/pull/2779>`_,
|
||||
`#2782 <https://github.com/fmtlib/fmt/pull/2782>`_,
|
||||
`#2783 <https://github.com/fmtlib/fmt/pull/2783>`_,
|
||||
`#2794 <https://github.com/fmtlib/fmt/issues/2794>`_,
|
||||
`#2796 <https://github.com/fmtlib/fmt/issues/2796>`_,
|
||||
`#2797 <https://github.com/fmtlib/fmt/pull/2797>`_,
|
||||
`#2801 <https://github.com/fmtlib/fmt/pull/2801>`_,
|
||||
`#2802 <https://github.com/fmtlib/fmt/pull/2802>`_,
|
||||
`#2808 <https://github.com/fmtlib/fmt/issues/2808>`_,
|
||||
`#2818 <https://github.com/fmtlib/fmt/issues/2818>`_,
|
||||
`#2819 <https://github.com/fmtlib/fmt/pull/2819>`_,
|
||||
`#2829 <https://github.com/fmtlib/fmt/issues/2829>`_,
|
||||
`#2835 <https://github.com/fmtlib/fmt/issues/2835>`_,
|
||||
`#2848 <https://github.com/fmtlib/fmt/issues/2848>`_,
|
||||
`#2860 <https://github.com/fmtlib/fmt/issues/2860>`_,
|
||||
`#2861 <https://github.com/fmtlib/fmt/pull/2861>`_,
|
||||
`#2882 <https://github.com/fmtlib/fmt/pull/2882>`_,
|
||||
`#2886 <https://github.com/fmtlib/fmt/issues/2886>`_,
|
||||
`#2891 <https://github.com/fmtlib/fmt/issues/2891>`_,
|
||||
`#2892 <https://github.com/fmtlib/fmt/pull/2892>`_,
|
||||
`#2895 <https://github.com/fmtlib/fmt/issues/2895>`_,
|
||||
`#2896 <https://github.com/fmtlib/fmt/issues/2896>`_,
|
||||
`#2903 <https://github.com/fmtlib/fmt/pull/2903>`_,
|
||||
`#2906 <https://github.com/fmtlib/fmt/issues/2906>`_,
|
||||
`#2908 <https://github.com/fmtlib/fmt/issues/2908>`_,
|
||||
`#2909 <https://github.com/fmtlib/fmt/pull/2909>`_,
|
||||
`#2920 <https://github.com/fmtlib/fmt/issues/2920>`_,
|
||||
`#2922 <https://github.com/fmtlib/fmt/pull/2922>`_,
|
||||
`#2927 <https://github.com/fmtlib/fmt/pull/2927>`_,
|
||||
`#2929 <https://github.com/fmtlib/fmt/pull/2929>`_,
|
||||
`#2936 <https://github.com/fmtlib/fmt/issues/2936>`_,
|
||||
`#2937 <https://github.com/fmtlib/fmt/pull/2937>`_,
|
||||
`#2938 <https://github.com/fmtlib/fmt/pull/2938>`_,
|
||||
`#2951 <https://github.com/fmtlib/fmt/pull/2951>`_,
|
||||
`#2954 <https://github.com/fmtlib/fmt/issues/2954>`_,
|
||||
`#2957 <https://github.com/fmtlib/fmt/pull/2957>`_,
|
||||
`#2958 <https://github.com/fmtlib/fmt/issues/2958>`_,
|
||||
`#2960 <https://github.com/fmtlib/fmt/pull/2960>`_).
|
||||
Thanks `@matrackif <https://github.com/matrackif>`_
|
||||
`@Tobi823 (Tobias Hellmann) <https://github.com/Tobi823>`_,
|
||||
`@ivan-volnov (Ivan Volnov) <https://github.com/ivan-volnov>`_,
|
||||
`@VasiliPupkin256 <https://github.com/VasiliPupkin256>`_,
|
||||
`@federico-busato (Federico) <https://github.com/federico-busato>`_,
|
||||
`@barcharcraz (Charlie Barto) <https://github.com/barcharcraz>`_,
|
||||
`@jk-jeon (Junekey Jeon) <https://github.com/jk-jeon>`_,
|
||||
`@HazardyKnusperkeks (Björn Schäpers)
|
||||
<https://github.com/HazardyKnusperkeks>`_,
|
||||
`@dalboris (Boris Dalstein) <https://github.com/dalboris>`_,
|
||||
`@seanm (Sean McBride) <https://github.com/seanm>`_,
|
||||
`@gsjaardema (Greg Sjaardema) <https://github.com/gsjaardema>`_,
|
||||
`@timsong-cpp <https://github.com/timsong-cpp>`_,
|
||||
`@seanm (Sean McBride) <https://github.com/seanm>`_,
|
||||
`@frithrah <https://github.com/frithrah>`_,
|
||||
`@chronoxor (Ivan Shynkarenka) <https://github.com/chronoxor>`_,
|
||||
`@Agga <https://github.com/Agga>`_,
|
||||
`@madmaxoft (Mattes D) <https://github.com/madmaxoft>`_,
|
||||
`@JurajX (Juraj) <https://github.com/JurajX>`_,
|
||||
`@phprus (Vladislav Shchapov) <https://github.com/phprus>`_,
|
||||
`@Dani-Hub (Daniel Krügler) <https://github.com/Dani-Hub>`_.
|
||||
|
||||
8.1.1 - 2022-01-06
|
||||
------------------
|
||||
|
||||
@ -148,6 +660,10 @@
|
||||
["
|
||||
aan"]
|
||||
|
||||
* Added an experimental ``?`` specifier for escaping strings.
|
||||
(`#2674 <https://github.com/fmtlib/fmt/pull/2674>`_).
|
||||
Thanks `@BRevzin (Barry Revzin) <https://github.com/BRevzin>`_.
|
||||
|
||||
* Switched to JSON-like representation of maps and sets for consistency with
|
||||
Python's ``str.format``.
|
||||
For example (`godbolt <https://godbolt.org/z/seKjoY9W5>`__):
|
||||
@ -367,7 +883,8 @@
|
||||
`@alexezeder (Alexey Ochapov) <https://github.com/alexezeder>`_,
|
||||
`@andrewcorrigan (Andrew Corrigan) <https://github.com/andrewcorrigan>`_,
|
||||
`@lucpelletier <https://github.com/lucpelletier>`_,
|
||||
`@HazardyKnusperkeks (Björn Schäpers) <https://github.com/HazardyKnusperkeks>`_.
|
||||
`@HazardyKnusperkeks (Björn Schäpers)
|
||||
<https://github.com/HazardyKnusperkeks>`_.
|
||||
|
||||
8.0.1 - 2021-07-02
|
||||
------------------
|
||||
|
10
Externals/fmt/README.rst
vendored
10
Externals/fmt/README.rst
vendored
@ -12,9 +12,6 @@
|
||||
.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg
|
||||
:target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true
|
||||
:target: https://ci.appveyor.com/project/vitaut/fmt
|
||||
|
||||
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
|
||||
:alt: fmt is continuously fuzzed at oss-fuzz
|
||||
:target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
|
||||
@ -33,6 +30,8 @@ help victims of the war in Ukraine: https://www.stopputin.net/.
|
||||
|
||||
`Documentation <https://fmt.dev>`__
|
||||
|
||||
`Cheat Sheets <https://hackingcpp.com/cpp/libs/fmt.html>`__
|
||||
|
||||
Q&A: ask questions on `StackOverflow with the tag fmt
|
||||
<https://stackoverflow.com/questions/tagged/fmt>`_.
|
||||
|
||||
@ -342,9 +341,12 @@ Projects using this library
|
||||
|
||||
* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
|
||||
|
||||
* `GemRB <https://gemrb.org/>`_: a portable open-source implementation of
|
||||
Bioware’s Infinity Engine
|
||||
|
||||
* `Grand Mountain Adventure
|
||||
<https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_:
|
||||
A beautiful open-world ski & snowboarding game
|
||||
a beautiful open-world ski & snowboarding game
|
||||
|
||||
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||
Player vs Player Gaming Network with tweaks
|
||||
|
2
Externals/fmt/fmt.vcxproj
vendored
2
Externals/fmt/fmt.vcxproj
vendored
@ -32,11 +32,11 @@
|
||||
<ClInclude Include="include/fmt/core.h" />
|
||||
<ClInclude Include="include/fmt/format-inl.h" />
|
||||
<ClInclude Include="include/fmt/format.h" />
|
||||
<ClInclude Include="include/fmt/locale.h" />
|
||||
<ClInclude Include="include/fmt/os.h" />
|
||||
<ClInclude Include="include/fmt/ostream.h" />
|
||||
<ClInclude Include="include/fmt/printf.h" />
|
||||
<ClInclude Include="include/fmt/ranges.h" />
|
||||
<ClInclude Include="include/fmt/std.h" />
|
||||
<ClInclude Include="include/fmt/xchar.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
54
Externals/fmt/include/fmt/chrono.h
vendored
54
Externals/fmt/include/fmt/chrono.h
vendored
@ -203,7 +203,7 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
}
|
||||
const auto min1 =
|
||||
(std::numeric_limits<IntermediateRep>::min)() / Factor::num;
|
||||
if (count < min1) {
|
||||
if (!std::is_unsigned<IntermediateRep>::value && count < min1) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
@ -345,7 +345,7 @@ auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
|
||||
if (detail::is_utf8() && loc != get_classic_locale()) {
|
||||
// char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
|
||||
// gcc-4.
|
||||
#if FMT_MSC_VER != 0 || \
|
||||
#if FMT_MSC_VERSION != 0 || \
|
||||
(defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
|
||||
// The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
|
||||
// and newer.
|
||||
@ -469,7 +469,7 @@ inline std::tm localtime(std::time_t time) {
|
||||
|
||||
bool fallback(int res) { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VER
|
||||
#if !FMT_MSC_VERSION
|
||||
bool fallback(detail::null<>) {
|
||||
using namespace fmt::detail;
|
||||
std::tm* tm = std::localtime(&time_);
|
||||
@ -515,7 +515,7 @@ inline std::tm gmtime(std::time_t time) {
|
||||
|
||||
bool fallback(int res) { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VER
|
||||
#if !FMT_MSC_VERSION
|
||||
bool fallback(detail::null<>) {
|
||||
std::tm* tm = std::gmtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
@ -1396,7 +1396,8 @@ inline bool isfinite(T) {
|
||||
// Converts value to Int and checks that it's in the range [0, upper).
|
||||
template <typename T, typename Int, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline Int to_nonnegative_int(T value, Int upper) {
|
||||
FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper),
|
||||
FMT_ASSERT(std::is_unsigned<Int>::value ||
|
||||
(value >= 0 && to_unsigned(value) <= to_unsigned(upper)),
|
||||
"invalid value");
|
||||
(void)upper;
|
||||
return static_cast<Int>(value);
|
||||
@ -1466,8 +1467,7 @@ inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||
// C++20 spec. If more than 18 fractional digits are required then returns 6 for
|
||||
// microseconds precision.
|
||||
template <long long Num, long long Den, int N = 0,
|
||||
bool Enabled =
|
||||
(N < 19) && (Num <= std::numeric_limits<long long>::max() / 10)>
|
||||
bool Enabled = (N < 19) && (Num <= max_value<long long>() / 10)>
|
||||
struct count_fractional_digits {
|
||||
static constexpr int value =
|
||||
Num % Den == 0 ? N : count_fractional_digits<Num * 10, Den, N + 1>::value;
|
||||
@ -1777,7 +1777,7 @@ struct chrono_formatter {
|
||||
format_to(std::back_inserter(buf), runtime("{:.{}f}"),
|
||||
std::fmod(val * static_cast<rep>(Period::num) /
|
||||
static_cast<rep>(Period::den),
|
||||
60),
|
||||
static_cast<rep>(60)),
|
||||
num_fractional_digits);
|
||||
if (negative) *out++ = '-';
|
||||
if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
|
||||
@ -2002,13 +2002,9 @@ template <typename Char, typename Duration>
|
||||
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char> : formatter<std::tm, Char> {
|
||||
FMT_CONSTEXPR formatter() {
|
||||
this->do_parse(default_specs,
|
||||
default_specs + sizeof(default_specs) / sizeof(Char));
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return this->do_parse(ctx.begin(), ctx.end(), true);
|
||||
basic_string_view<Char> default_specs =
|
||||
detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
|
||||
this->do_parse(default_specs.begin(), default_specs.end());
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
@ -2016,15 +2012,8 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
return formatter<std::tm, Char>::format(localtime(val), ctx);
|
||||
}
|
||||
|
||||
static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'};
|
||||
};
|
||||
|
||||
template <typename Char, typename Duration>
|
||||
constexpr const Char
|
||||
formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||
Char>::default_specs[];
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
private:
|
||||
enum class spec {
|
||||
@ -2036,13 +2025,18 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
basic_string_view<Char> specs;
|
||||
|
||||
protected:
|
||||
template <typename It>
|
||||
FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false)
|
||||
-> It {
|
||||
template <typename It> FMT_CONSTEXPR auto do_parse(It begin, It end) -> It {
|
||||
if (begin != end && *begin == ':') ++begin;
|
||||
end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
|
||||
if (!with_default || end != begin)
|
||||
specs = {begin, detail::to_unsigned(end - begin)};
|
||||
// Replace default spec only if the new spec is not empty.
|
||||
if (end != begin) specs = {begin, detail::to_unsigned(end - begin)};
|
||||
return end;
|
||||
}
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
auto end = this->do_parse(ctx.begin(), ctx.end());
|
||||
// basic_string_view<>::compare isn't constexpr before C++17.
|
||||
if (specs.size() == 2 && specs[0] == Char('%')) {
|
||||
if (specs[1] == Char('F'))
|
||||
@ -2053,12 +2047,6 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
return end;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return this->do_parse(ctx.begin(), ctx.end());
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::tm& tm, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
|
61
Externals/fmt/include/fmt/color.h
vendored
61
Externals/fmt/include/fmt/color.h
vendored
@ -10,13 +10,6 @@
|
||||
|
||||
#include "format.h"
|
||||
|
||||
// __declspec(deprecated) is broken in some MSVC versions.
|
||||
#if FMT_MSC_VER
|
||||
# define FMT_DEPRECATED_NONMSVC
|
||||
#else
|
||||
# define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
FMT_MODULE_EXPORT_BEGIN
|
||||
|
||||
@ -270,16 +263,6 @@ class text_style {
|
||||
return lhs |= rhs;
|
||||
}
|
||||
|
||||
FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=(
|
||||
const text_style& rhs) {
|
||||
return and_assign(rhs);
|
||||
}
|
||||
|
||||
FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style
|
||||
operator&(text_style lhs, const text_style& rhs) {
|
||||
return lhs.and_assign(rhs);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR bool has_foreground() const noexcept {
|
||||
return set_foreground_color;
|
||||
}
|
||||
@ -315,36 +298,9 @@ class text_style {
|
||||
}
|
||||
}
|
||||
|
||||
// DEPRECATED!
|
||||
FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) {
|
||||
if (!set_foreground_color) {
|
||||
set_foreground_color = rhs.set_foreground_color;
|
||||
foreground_color = rhs.foreground_color;
|
||||
} else if (rhs.set_foreground_color) {
|
||||
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
|
||||
FMT_THROW(format_error("can't AND a terminal color"));
|
||||
foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
|
||||
}
|
||||
friend FMT_CONSTEXPR text_style fg(detail::color_type foreground) noexcept;
|
||||
|
||||
if (!set_background_color) {
|
||||
set_background_color = rhs.set_background_color;
|
||||
background_color = rhs.background_color;
|
||||
} else if (rhs.set_background_color) {
|
||||
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
|
||||
FMT_THROW(format_error("can't AND a terminal color"));
|
||||
background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
|
||||
}
|
||||
|
||||
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
|
||||
static_cast<uint8_t>(rhs.ems));
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend FMT_CONSTEXPR_DECL text_style
|
||||
fg(detail::color_type foreground) noexcept;
|
||||
|
||||
friend FMT_CONSTEXPR_DECL text_style
|
||||
bg(detail::color_type background) noexcept;
|
||||
friend FMT_CONSTEXPR text_style bg(detail::color_type background) noexcept;
|
||||
|
||||
detail::color_type foreground_color;
|
||||
detail::color_type background_color;
|
||||
@ -527,7 +483,7 @@ template <typename S, typename Char = char_t<S>>
|
||||
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buf;
|
||||
detail::vformat_to(buf, ts, to_string_view(format), args);
|
||||
detail::vformat_to(buf, ts, detail::to_string_view(format), args);
|
||||
if (detail::is_utf8()) {
|
||||
detail::print(f, basic_string_view<Char>(buf.begin(), buf.size()));
|
||||
} else {
|
||||
@ -577,7 +533,7 @@ inline std::basic_string<Char> vformat(
|
||||
const text_style& ts, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buf;
|
||||
detail::vformat_to(buf, ts, to_string_view(format_str), args);
|
||||
detail::vformat_to(buf, ts, detail::to_string_view(format_str), args);
|
||||
return fmt::to_string(buf);
|
||||
}
|
||||
|
||||
@ -596,7 +552,7 @@ inline std::basic_string<Char> vformat(
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
return fmt::vformat(ts, to_string_view(format_str),
|
||||
return fmt::vformat(ts, detail::to_string_view(format_str),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -631,7 +587,7 @@ template <typename OutputIt, typename S, typename... Args,
|
||||
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
|
||||
Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, ts, to_string_view(format_str),
|
||||
return vformat_to(out, ts, detail::to_string_view(format_str),
|
||||
fmt::make_format_args<buffer_context<char_t<S>>>(args...));
|
||||
}
|
||||
|
||||
@ -678,8 +634,9 @@ struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::print("Elapsed time: {s:.2f} seconds",
|
||||
fmt::styled(1.23, fmt::fg(fmt::color::green) | fmt::bg(fmt::color::blue)));
|
||||
fmt::print("Elapsed time: {0:.2f} seconds",
|
||||
fmt::styled(1.23, fmt::fg(fmt::color::green) |
|
||||
fmt::bg(fmt::color::blue)));
|
||||
\endrst
|
||||
*/
|
||||
template <typename T>
|
||||
|
33
Externals/fmt/include/fmt/compile.h
vendored
33
Externals/fmt/include/fmt/compile.h
vendored
@ -14,8 +14,8 @@ FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
template <typename Char, typename InputIt>
|
||||
inline counting_iterator copy_str(InputIt begin, InputIt end,
|
||||
counting_iterator it) {
|
||||
FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end,
|
||||
counting_iterator it) {
|
||||
return it + (end - begin);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
||||
# define FMT_COMPILE(s) FMT_STRING(s)
|
||||
#endif
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
template <typename Char, size_t N,
|
||||
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||
struct udl_compiled_string : compiled_string {
|
||||
@ -337,10 +337,11 @@ template <typename T, typename Char>
|
||||
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
||||
size_t pos, int next_arg_id) {
|
||||
str.remove_prefix(pos);
|
||||
auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id);
|
||||
auto ctx = compile_parse_context<Char>(str, max_value<int>(), nullptr, {},
|
||||
next_arg_id);
|
||||
auto f = formatter<T, Char>();
|
||||
auto end = f.parse(ctx);
|
||||
return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1,
|
||||
return {f, pos + fmt::detail::to_unsigned(end - str.data()),
|
||||
next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};
|
||||
}
|
||||
|
||||
@ -396,13 +397,20 @@ constexpr auto parse_replacement_field_then_tail(S format_str) {
|
||||
return parse_tail<Args, END_POS + 1, NEXT_ID>(
|
||||
field<char_type, typename field_type<T>::type, ARG_INDEX>(),
|
||||
format_str);
|
||||
} else if constexpr (c == ':') {
|
||||
} else if constexpr (c != ':') {
|
||||
FMT_THROW(format_error("expected ':'"));
|
||||
} else {
|
||||
constexpr auto result = parse_specs<typename field_type<T>::type>(
|
||||
str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);
|
||||
return parse_tail<Args, result.end, result.next_arg_id>(
|
||||
spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
|
||||
result.fmt},
|
||||
format_str);
|
||||
if constexpr (result.end >= str.size() || str[result.end] != '}') {
|
||||
FMT_THROW(format_error("expected '}'"));
|
||||
return 0;
|
||||
} else {
|
||||
return parse_tail<Args, result.end + 1, result.next_arg_id>(
|
||||
spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
|
||||
result.fmt},
|
||||
format_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,7 +575,8 @@ format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
size_t formatted_size(const S& format_str, const Args&... args) {
|
||||
FMT_CONSTEXPR20 size_t formatted_size(const S& format_str,
|
||||
const Args&... args) {
|
||||
return fmt::format_to(detail::counting_iterator(), format_str, args...)
|
||||
.count();
|
||||
}
|
||||
@ -586,7 +595,7 @@ void print(const S& format_str, const Args&... args) {
|
||||
print(stdout, format_str, args...);
|
||||
}
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
inline namespace literals {
|
||||
template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
|
||||
using char_t = remove_cvref_t<decltype(Str.data[0])>;
|
||||
|
611
Externals/fmt/include/fmt/core.h
vendored
611
Externals/fmt/include/fmt/core.h
vendored
File diff suppressed because it is too large
Load Diff
917
Externals/fmt/include/fmt/format-inl.h
vendored
917
Externals/fmt/include/fmt/format-inl.h
vendored
@ -80,7 +80,8 @@ FMT_FUNC void report_error(format_func func, int error_code,
|
||||
inline void fwrite_fully(const void* ptr, size_t size, size_t count,
|
||||
FILE* stream) {
|
||||
size_t written = std::fwrite(ptr, size, count, stream);
|
||||
if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
|
||||
if (written < count)
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||
}
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
@ -116,7 +117,7 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
#if !FMT_MSC_VER
|
||||
#if !FMT_MSC_VERSION
|
||||
FMT_API FMT_FUNC format_error::~format_error() noexcept = default;
|
||||
#endif
|
||||
|
||||
@ -128,640 +129,10 @@ FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T = void> struct basic_impl_data {
|
||||
// Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
|
||||
// These are generated by support/compute-powers.py.
|
||||
static constexpr uint64_t pow10_significands[87] = {
|
||||
0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
|
||||
0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
|
||||
0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
|
||||
0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
|
||||
0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
|
||||
0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
|
||||
0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
|
||||
0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
|
||||
0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
|
||||
0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
|
||||
0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
|
||||
0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
|
||||
0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
|
||||
0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
|
||||
0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
|
||||
0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
|
||||
0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
|
||||
0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
|
||||
0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
|
||||
0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
|
||||
0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
|
||||
0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
|
||||
0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
|
||||
0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
|
||||
0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
|
||||
0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
|
||||
0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
|
||||
0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
|
||||
0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
|
||||
};
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wnarrowing"
|
||||
#endif
|
||||
// Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
|
||||
// to significands above.
|
||||
static constexpr int16_t pow10_exponents[87] = {
|
||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
|
||||
-927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
|
||||
-635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
|
||||
-343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
|
||||
-50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
|
||||
242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
|
||||
534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
|
||||
827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static constexpr uint64_t power_of_10_64[20] = {
|
||||
1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
|
||||
10000000000000000000ULL};
|
||||
};
|
||||
|
||||
// This is a struct rather than an alias to avoid shadowing warnings in gcc.
|
||||
struct impl_data : basic_impl_data<> {};
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
template <typename T>
|
||||
constexpr uint64_t basic_impl_data<T>::pow10_significands[];
|
||||
template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[];
|
||||
template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[];
|
||||
#endif
|
||||
|
||||
template <typename T> struct bits {
|
||||
static FMT_CONSTEXPR_DECL const int value =
|
||||
static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
|
||||
};
|
||||
|
||||
// A floating-point number f * pow(2, e) where F is an unsigned type.
|
||||
template <typename F> struct basic_fp {
|
||||
F f;
|
||||
int e;
|
||||
|
||||
static constexpr const int num_significand_bits = bits<F>::value;
|
||||
|
||||
constexpr basic_fp() : f(0), e(0) {}
|
||||
constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
|
||||
|
||||
// Constructs fp from an IEEE754 floating-point number.
|
||||
template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
|
||||
|
||||
// Assigns n to this and return true iff predecessor is closer than successor.
|
||||
template <typename Float> FMT_CONSTEXPR auto assign(Float n) -> bool {
|
||||
static_assert((std::numeric_limits<Float>::is_iec559 &&
|
||||
std::numeric_limits<Float>::digits <= 113) ||
|
||||
is_float128<Float>::value,
|
||||
"unsupported FP");
|
||||
// Assume Float is in the format [sign][exponent][significand].
|
||||
using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint;
|
||||
const auto num_float_significand_bits =
|
||||
detail::num_significand_bits<Float>();
|
||||
const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
|
||||
const auto significand_mask = implicit_bit - 1;
|
||||
auto u = bit_cast<carrier_uint>(n);
|
||||
f = static_cast<F>(u & significand_mask);
|
||||
auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
|
||||
num_float_significand_bits);
|
||||
// The predecessor is closer if n is a normalized power of 2 (f == 0) other
|
||||
// than the smallest normalized number (biased_e > 1).
|
||||
auto is_predecessor_closer = f == 0 && biased_e > 1;
|
||||
if (biased_e == 0)
|
||||
biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
|
||||
else if (has_implicit_bit<Float>())
|
||||
f += static_cast<F>(implicit_bit);
|
||||
e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
|
||||
if (!has_implicit_bit<Float>()) ++e;
|
||||
return is_predecessor_closer;
|
||||
}
|
||||
};
|
||||
|
||||
using fp = basic_fp<unsigned long long>;
|
||||
|
||||
// Normalizes the value converted from double and multiplied by (1 << SHIFT).
|
||||
template <int SHIFT = 0, typename F>
|
||||
FMT_CONSTEXPR basic_fp<F> normalize(basic_fp<F> value) {
|
||||
// Handle subnormals.
|
||||
const auto implicit_bit = F(1) << num_significand_bits<double>();
|
||||
const auto shifted_implicit_bit = implicit_bit << SHIFT;
|
||||
while ((value.f & shifted_implicit_bit) == 0) {
|
||||
value.f <<= 1;
|
||||
--value.e;
|
||||
}
|
||||
// Subtract 1 to account for hidden bit.
|
||||
const auto offset =
|
||||
fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1;
|
||||
value.f <<= offset;
|
||||
value.e -= offset;
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename F> inline bool operator==(basic_fp<F> x, basic_fp<F> y) {
|
||||
return x.f == y.f && x.e == y.e;
|
||||
}
|
||||
|
||||
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
|
||||
FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
|
||||
#if FMT_USE_INT128
|
||||
auto product = static_cast<__uint128_t>(lhs) * rhs;
|
||||
auto f = static_cast<uint64_t>(product >> 64);
|
||||
return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
|
||||
#else
|
||||
// Multiply 32-bit parts of significands.
|
||||
uint64_t mask = (1ULL << 32) - 1;
|
||||
uint64_t a = lhs >> 32, b = lhs & mask;
|
||||
uint64_t c = rhs >> 32, d = rhs & mask;
|
||||
uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
|
||||
// Compute mid 64-bit of result and round.
|
||||
uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
|
||||
return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR inline fp operator*(fp x, fp y) {
|
||||
return {multiply(x.f, y.f), x.e + y.e + 64};
|
||||
}
|
||||
|
||||
// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
|
||||
// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
|
||||
FMT_CONSTEXPR inline fp get_cached_power(int min_exponent,
|
||||
int& pow10_exponent) {
|
||||
const int shift = 32;
|
||||
// log10(2) = 0x0.4d104d427de7fbcc...
|
||||
const int64_t significand = 0x4d104d427de7fbcc;
|
||||
int index = static_cast<int>(
|
||||
((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
|
||||
((int64_t(1) << shift) - 1)) // ceil
|
||||
>> 32 // arithmetic shift
|
||||
);
|
||||
// Decimal exponent of the first (smallest) cached power of 10.
|
||||
const int first_dec_exp = -348;
|
||||
// Difference between 2 consecutive decimal exponents in cached powers of 10.
|
||||
const int dec_exp_step = 8;
|
||||
index = (index - first_dec_exp - 1) / dec_exp_step + 1;
|
||||
pow10_exponent = first_dec_exp + index * dec_exp_step;
|
||||
return {impl_data::pow10_significands[index],
|
||||
impl_data::pow10_exponents[index]};
|
||||
}
|
||||
|
||||
class bigint {
|
||||
private:
|
||||
// A bigint is stored as an array of bigits (big digits), with bigit at index
|
||||
// 0 being the least significant one.
|
||||
using bigit = uint32_t;
|
||||
using double_bigit = uint64_t;
|
||||
enum { bigits_capacity = 32 };
|
||||
basic_memory_buffer<bigit, bigits_capacity> bigits_;
|
||||
int exp_;
|
||||
|
||||
FMT_CONSTEXPR20 bigit operator[](int index) const {
|
||||
return bigits_[to_unsigned(index)];
|
||||
}
|
||||
FMT_CONSTEXPR20 bigit& operator[](int index) {
|
||||
return bigits_[to_unsigned(index)];
|
||||
}
|
||||
|
||||
static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value;
|
||||
|
||||
friend struct formatter<bigint>;
|
||||
|
||||
FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
|
||||
auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
|
||||
(*this)[index] = static_cast<bigit>(result);
|
||||
borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR20 void remove_leading_zeros() {
|
||||
int num_bigits = static_cast<int>(bigits_.size()) - 1;
|
||||
while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
|
||||
bigits_.resize(to_unsigned(num_bigits + 1));
|
||||
}
|
||||
|
||||
// Computes *this -= other assuming aligned bigints and *this >= other.
|
||||
FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
|
||||
FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
|
||||
FMT_ASSERT(compare(*this, other) >= 0, "");
|
||||
bigit borrow = 0;
|
||||
int i = other.exp_ - exp_;
|
||||
for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
|
||||
subtract_bigits(i, other.bigits_[j], borrow);
|
||||
while (borrow > 0) subtract_bigits(i, 0, borrow);
|
||||
remove_leading_zeros();
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR20 void multiply(uint32_t value) {
|
||||
const double_bigit wide_value = value;
|
||||
bigit carry = 0;
|
||||
for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
|
||||
double_bigit result = bigits_[i] * wide_value + carry;
|
||||
bigits_[i] = static_cast<bigit>(result);
|
||||
carry = static_cast<bigit>(result >> bigit_bits);
|
||||
}
|
||||
if (carry != 0) bigits_.push_back(carry);
|
||||
}
|
||||
|
||||
template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
|
||||
std::is_same<UInt, uint128_t>::value)>
|
||||
FMT_CONSTEXPR20 void multiply(UInt value) {
|
||||
using half_uint =
|
||||
conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>;
|
||||
const int shift = num_bits<half_uint>() - bigit_bits;
|
||||
const UInt lower = static_cast<half_uint>(value);
|
||||
const UInt upper = value >> num_bits<half_uint>();
|
||||
UInt carry = 0;
|
||||
for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
|
||||
UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
|
||||
carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
|
||||
(carry >> bigit_bits);
|
||||
bigits_[i] = static_cast<bigit>(result);
|
||||
}
|
||||
while (carry != 0) {
|
||||
bigits_.push_back(static_cast<bigit>(carry));
|
||||
carry >>= bigit_bits;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
|
||||
std::is_same<UInt, uint128_t>::value)>
|
||||
FMT_CONSTEXPR20 void assign(UInt n) {
|
||||
size_t num_bigits = 0;
|
||||
do {
|
||||
bigits_[num_bigits++] = static_cast<bigit>(n);
|
||||
n >>= bigit_bits;
|
||||
} while (n != 0);
|
||||
bigits_.resize(num_bigits);
|
||||
exp_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR20 bigint() : exp_(0) {}
|
||||
explicit bigint(uint64_t n) { assign(n); }
|
||||
|
||||
bigint(const bigint&) = delete;
|
||||
void operator=(const bigint&) = delete;
|
||||
|
||||
FMT_CONSTEXPR20 void assign(const bigint& other) {
|
||||
auto size = other.bigits_.size();
|
||||
bigits_.resize(size);
|
||||
auto data = other.bigits_.data();
|
||||
std::copy(data, data + size, make_checked(bigits_.data(), size));
|
||||
exp_ = other.exp_;
|
||||
}
|
||||
|
||||
template <typename Int> FMT_CONSTEXPR20 void operator=(Int n) {
|
||||
FMT_ASSERT(n > 0, "");
|
||||
assign(uint64_or_128_t<Int>(n));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR20 int num_bigits() const {
|
||||
return static_cast<int>(bigits_.size()) + exp_;
|
||||
}
|
||||
|
||||
FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {
|
||||
FMT_ASSERT(shift >= 0, "");
|
||||
exp_ += shift / bigit_bits;
|
||||
shift %= bigit_bits;
|
||||
if (shift == 0) return *this;
|
||||
bigit carry = 0;
|
||||
for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
|
||||
bigit c = bigits_[i] >> (bigit_bits - shift);
|
||||
bigits_[i] = (bigits_[i] << shift) + carry;
|
||||
carry = c;
|
||||
}
|
||||
if (carry != 0) bigits_.push_back(carry);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
|
||||
FMT_ASSERT(value > 0, "");
|
||||
multiply(uint32_or_64_or_128_t<Int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
|
||||
int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
|
||||
if (num_lhs_bigits != num_rhs_bigits)
|
||||
return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
|
||||
int i = static_cast<int>(lhs.bigits_.size()) - 1;
|
||||
int j = static_cast<int>(rhs.bigits_.size()) - 1;
|
||||
int end = i - j;
|
||||
if (end < 0) end = 0;
|
||||
for (; i >= end; --i, --j) {
|
||||
bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
|
||||
if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
|
||||
}
|
||||
if (i != j) return i > j ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns compare(lhs1 + lhs2, rhs).
|
||||
friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
|
||||
const bigint& rhs) {
|
||||
int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits());
|
||||
int num_rhs_bigits = rhs.num_bigits();
|
||||
if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
|
||||
if (max_lhs_bigits > num_rhs_bigits) return 1;
|
||||
auto get_bigit = [](const bigint& n, int i) -> bigit {
|
||||
return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
|
||||
};
|
||||
double_bigit borrow = 0;
|
||||
int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_);
|
||||
for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
|
||||
double_bigit sum =
|
||||
static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
|
||||
bigit rhs_bigit = get_bigit(rhs, i);
|
||||
if (sum > rhs_bigit + borrow) return 1;
|
||||
borrow = rhs_bigit + borrow - sum;
|
||||
if (borrow > 1) return -1;
|
||||
borrow <<= bigit_bits;
|
||||
}
|
||||
return borrow != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
// Assigns pow(10, exp) to this bigint.
|
||||
FMT_CONSTEXPR20 void assign_pow10(int exp) {
|
||||
FMT_ASSERT(exp >= 0, "");
|
||||
if (exp == 0) return *this = 1;
|
||||
// Find the top bit.
|
||||
int bitmask = 1;
|
||||
while (exp >= bitmask) bitmask <<= 1;
|
||||
bitmask >>= 1;
|
||||
// pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
|
||||
// repeated squaring and multiplication.
|
||||
*this = 5;
|
||||
bitmask >>= 1;
|
||||
while (bitmask != 0) {
|
||||
square();
|
||||
if ((exp & bitmask) != 0) *this *= 5;
|
||||
bitmask >>= 1;
|
||||
}
|
||||
*this <<= exp; // Multiply by pow(2, exp) by shifting.
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR20 void square() {
|
||||
int num_bigits = static_cast<int>(bigits_.size());
|
||||
int num_result_bigits = 2 * num_bigits;
|
||||
basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
|
||||
bigits_.resize(to_unsigned(num_result_bigits));
|
||||
auto sum = uint128_t();
|
||||
for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
|
||||
// Compute bigit at position bigit_index of the result by adding
|
||||
// cross-product terms n[i] * n[j] such that i + j == bigit_index.
|
||||
for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
|
||||
// Most terms are multiplied twice which can be optimized in the future.
|
||||
sum += static_cast<double_bigit>(n[i]) * n[j];
|
||||
}
|
||||
(*this)[bigit_index] = static_cast<bigit>(sum);
|
||||
sum >>= bits<bigit>::value; // Compute the carry.
|
||||
}
|
||||
// Do the same for the top half.
|
||||
for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
|
||||
++bigit_index) {
|
||||
for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
|
||||
sum += static_cast<double_bigit>(n[i++]) * n[j--];
|
||||
(*this)[bigit_index] = static_cast<bigit>(sum);
|
||||
sum >>= bits<bigit>::value;
|
||||
}
|
||||
remove_leading_zeros();
|
||||
exp_ *= 2;
|
||||
}
|
||||
|
||||
// If this bigint has a bigger exponent than other, adds trailing zero to make
|
||||
// exponents equal. This simplifies some operations such as subtraction.
|
||||
FMT_CONSTEXPR20 void align(const bigint& other) {
|
||||
int exp_difference = exp_ - other.exp_;
|
||||
if (exp_difference <= 0) return;
|
||||
int num_bigits = static_cast<int>(bigits_.size());
|
||||
bigits_.resize(to_unsigned(num_bigits + exp_difference));
|
||||
for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
|
||||
bigits_[j] = bigits_[i];
|
||||
std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
|
||||
exp_ -= exp_difference;
|
||||
}
|
||||
|
||||
// Divides this bignum by divisor, assigning the remainder to this and
|
||||
// returning the quotient.
|
||||
FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {
|
||||
FMT_ASSERT(this != &divisor, "");
|
||||
if (compare(*this, divisor) < 0) return 0;
|
||||
FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
|
||||
align(divisor);
|
||||
int quotient = 0;
|
||||
do {
|
||||
subtract_aligned(divisor);
|
||||
++quotient;
|
||||
} while (compare(*this, divisor) >= 0);
|
||||
return quotient;
|
||||
}
|
||||
};
|
||||
|
||||
enum class round_direction { unknown, up, down };
|
||||
|
||||
// Given the divisor (normally a power of 10), the remainder = v % divisor for
|
||||
// some number v and the error, returns whether v should be rounded up, down, or
|
||||
// whether the rounding direction can't be determined due to error.
|
||||
// error should be less than divisor / 2.
|
||||
FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,
|
||||
uint64_t remainder,
|
||||
uint64_t error) {
|
||||
FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow.
|
||||
FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow.
|
||||
FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow.
|
||||
// Round down if (remainder + error) * 2 <= divisor.
|
||||
if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)
|
||||
return round_direction::down;
|
||||
// Round up if (remainder - error) * 2 >= divisor.
|
||||
if (remainder >= error &&
|
||||
remainder - error >= divisor - (remainder - error)) {
|
||||
return round_direction::up;
|
||||
}
|
||||
return round_direction::unknown;
|
||||
}
|
||||
|
||||
namespace digits {
|
||||
enum result {
|
||||
more, // Generate more digits.
|
||||
done, // Done generating digits.
|
||||
error // Digit generation cancelled due to an error.
|
||||
};
|
||||
}
|
||||
|
||||
struct gen_digits_handler {
|
||||
char* buf;
|
||||
int size;
|
||||
int precision;
|
||||
int exp10;
|
||||
bool fixed;
|
||||
|
||||
FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,
|
||||
uint64_t remainder, uint64_t error,
|
||||
bool integral) {
|
||||
FMT_ASSERT(remainder < divisor, "");
|
||||
buf[size++] = digit;
|
||||
if (!integral && error >= remainder) return digits::error;
|
||||
if (size < precision) return digits::more;
|
||||
if (!integral) {
|
||||
// Check if error * 2 < divisor with overflow prevention.
|
||||
// The check is not needed for the integral part because error = 1
|
||||
// and divisor > (1 << 32) there.
|
||||
if (error >= divisor || error >= divisor - error) return digits::error;
|
||||
} else {
|
||||
FMT_ASSERT(error == 1 && divisor > 2, "");
|
||||
}
|
||||
auto dir = get_round_direction(divisor, remainder, error);
|
||||
if (dir != round_direction::up)
|
||||
return dir == round_direction::down ? digits::done : digits::error;
|
||||
++buf[size - 1];
|
||||
for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
|
||||
buf[i] = '0';
|
||||
++buf[i - 1];
|
||||
}
|
||||
if (buf[0] > '9') {
|
||||
buf[0] = '1';
|
||||
if (fixed)
|
||||
buf[size++] = '0';
|
||||
else
|
||||
++exp10;
|
||||
}
|
||||
return digits::done;
|
||||
}
|
||||
};
|
||||
|
||||
inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) {
|
||||
// Adjust fixed precision by exponent because it is relative to decimal
|
||||
// point.
|
||||
if (exp10 > 0 && precision > max_value<int>() - exp10)
|
||||
FMT_THROW(format_error("number is too big"));
|
||||
precision += exp10;
|
||||
}
|
||||
|
||||
// Generates output using the Grisu digit-gen algorithm.
|
||||
// error: the size of the region (lower, upper) outside of which numbers
|
||||
// definitely do not round to value (Delta in Grisu3).
|
||||
FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits(
|
||||
fp value, uint64_t error, int& exp, gen_digits_handler& handler) {
|
||||
const fp one(1ULL << -value.e, value.e);
|
||||
// The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
|
||||
// zero because it contains a product of two 64-bit numbers with MSB set (due
|
||||
// to normalization) - 1, shifted right by at most 60 bits.
|
||||
auto integral = static_cast<uint32_t>(value.f >> -one.e);
|
||||
FMT_ASSERT(integral != 0, "");
|
||||
FMT_ASSERT(integral == value.f >> -one.e, "");
|
||||
// The fractional part of scaled value (p2 in Grisu) c = value % one.
|
||||
uint64_t fractional = value.f & (one.f - 1);
|
||||
exp = count_digits(integral); // kappa in Grisu.
|
||||
// Non-fixed formats require at least one digit and no precision adjustment.
|
||||
if (handler.fixed) {
|
||||
adjust_precision(handler.precision, exp + handler.exp10);
|
||||
// Check if precision is satisfied just by leading zeros, e.g.
|
||||
// format("{:.2f}", 0.001) gives "0.00" without generating any digits.
|
||||
if (handler.precision <= 0) {
|
||||
if (handler.precision < 0) return digits::done;
|
||||
// Divide by 10 to prevent overflow.
|
||||
uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e;
|
||||
auto dir = get_round_direction(divisor, value.f / 10, error * 10);
|
||||
if (dir == round_direction::unknown) return digits::error;
|
||||
handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';
|
||||
return digits::done;
|
||||
}
|
||||
}
|
||||
// Generate digits for the integral part. This can produce up to 10 digits.
|
||||
do {
|
||||
uint32_t digit = 0;
|
||||
auto divmod_integral = [&](uint32_t divisor) {
|
||||
digit = integral / divisor;
|
||||
integral %= divisor;
|
||||
};
|
||||
// This optimization by Milo Yip reduces the number of integer divisions by
|
||||
// one per iteration.
|
||||
switch (exp) {
|
||||
case 10:
|
||||
divmod_integral(1000000000);
|
||||
break;
|
||||
case 9:
|
||||
divmod_integral(100000000);
|
||||
break;
|
||||
case 8:
|
||||
divmod_integral(10000000);
|
||||
break;
|
||||
case 7:
|
||||
divmod_integral(1000000);
|
||||
break;
|
||||
case 6:
|
||||
divmod_integral(100000);
|
||||
break;
|
||||
case 5:
|
||||
divmod_integral(10000);
|
||||
break;
|
||||
case 4:
|
||||
divmod_integral(1000);
|
||||
break;
|
||||
case 3:
|
||||
divmod_integral(100);
|
||||
break;
|
||||
case 2:
|
||||
divmod_integral(10);
|
||||
break;
|
||||
case 1:
|
||||
digit = integral;
|
||||
integral = 0;
|
||||
break;
|
||||
default:
|
||||
FMT_ASSERT(false, "invalid number of digits");
|
||||
}
|
||||
--exp;
|
||||
auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;
|
||||
auto result = handler.on_digit(static_cast<char>('0' + digit),
|
||||
impl_data::power_of_10_64[exp] << -one.e,
|
||||
remainder, error, true);
|
||||
if (result != digits::more) return result;
|
||||
} while (exp > 0);
|
||||
// Generate digits for the fractional part.
|
||||
for (;;) {
|
||||
fractional *= 10;
|
||||
error *= 10;
|
||||
char digit = static_cast<char>('0' + (fractional >> -one.e));
|
||||
fractional &= one.f - 1;
|
||||
--exp;
|
||||
auto result = handler.on_digit(digit, one.f, fractional, error, false);
|
||||
if (result != digits::more) return result;
|
||||
}
|
||||
}
|
||||
|
||||
inline FMT_CONSTEXPR20 uint128_fallback& uint128_fallback::operator+=(
|
||||
uint64_t n) noexcept {
|
||||
if (is_constant_evaluated()) {
|
||||
lo_ += n;
|
||||
hi_ += (lo_ < n ? 1 : 0);
|
||||
return *this;
|
||||
}
|
||||
#if FMT_HAS_BUILTIN(__builtin_addcll)
|
||||
unsigned long long carry;
|
||||
lo_ = __builtin_addcll(lo_, n, 0, &carry);
|
||||
hi_ += carry;
|
||||
#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)
|
||||
unsigned long long result;
|
||||
auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
|
||||
lo_ = result;
|
||||
hi_ += carry;
|
||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
||||
auto carry = _addcarry_u64(0, lo_, n, &lo_);
|
||||
_addcarry_u64(carry, hi_, 0, &hi_);
|
||||
#else
|
||||
lo_ += n;
|
||||
hi_ += (lo_ < n ? 1 : 0);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compilers should be able to optimize this into the ror instruction.
|
||||
FMT_CONSTEXPR inline uint32_t rotr(uint32_t n, uint32_t r) noexcept {
|
||||
r &= 31;
|
||||
@ -1966,7 +1337,7 @@ template <typename T> decimal_fp<T> to_decimal(T x) noexcept {
|
||||
|
||||
if (r < deltai) {
|
||||
// Exclude the right endpoint if necessary.
|
||||
if (r == 0 && z_mul.is_integer && !include_right_endpoint) {
|
||||
if (r == 0 && (z_mul.is_integer & !include_right_endpoint)) {
|
||||
--ret_value.significand;
|
||||
r = float_info<T>::big_divisor;
|
||||
goto small_divisor_case_label;
|
||||
@ -1975,26 +1346,11 @@ template <typename T> decimal_fp<T> to_decimal(T x) noexcept {
|
||||
goto small_divisor_case_label;
|
||||
} else {
|
||||
// r == deltai; compare fractional parts.
|
||||
const carrier_uint two_fl = two_fc - 1;
|
||||
const typename cache_accessor<T>::compute_mul_parity_result x_mul =
|
||||
cache_accessor<T>::compute_mul_parity(two_fc - 1, cache, beta);
|
||||
|
||||
if (!include_left_endpoint ||
|
||||
exponent < float_info<T>::case_fc_pm_half_lower_threshold ||
|
||||
exponent > float_info<T>::divisibility_check_by_5_threshold) {
|
||||
// If the left endpoint is not included, the condition for
|
||||
// success is z^(f) < delta^(f) (odd parity).
|
||||
// Otherwise, the inequalities on exponent ensure that
|
||||
// x is not an integer, so if z^(f) >= delta^(f) (even parity), we in fact
|
||||
// have strict inequality.
|
||||
if (!cache_accessor<T>::compute_mul_parity(two_fl, cache, beta).parity) {
|
||||
goto small_divisor_case_label;
|
||||
}
|
||||
} else {
|
||||
const typename cache_accessor<T>::compute_mul_parity_result x_mul =
|
||||
cache_accessor<T>::compute_mul_parity(two_fl, cache, beta);
|
||||
if (!x_mul.parity && !x_mul.is_integer) {
|
||||
goto small_divisor_case_label;
|
||||
}
|
||||
}
|
||||
if (!(x_mul.parity | (x_mul.is_integer & include_left_endpoint)))
|
||||
goto small_divisor_case_label;
|
||||
}
|
||||
ret_value.exponent = minus_k + float_info<T>::kappa + 1;
|
||||
|
||||
@ -2033,149 +1389,12 @@ small_divisor_case_label:
|
||||
// or equivalently, when y is an integer.
|
||||
if (y_mul.parity != approx_y_parity)
|
||||
--ret_value.significand;
|
||||
else if (y_mul.is_integer && ret_value.significand % 2 != 0)
|
||||
else if (y_mul.is_integer & (ret_value.significand % 2 != 0))
|
||||
--ret_value.significand;
|
||||
return ret_value;
|
||||
}
|
||||
} // namespace dragonbox
|
||||
|
||||
// format_dragon flags.
|
||||
enum dragon {
|
||||
predecessor_closer = 1,
|
||||
fixup = 2, // Run fixup to correct exp10 which can be off by one.
|
||||
fixed = 4,
|
||||
};
|
||||
|
||||
// Formats a floating-point number using a variation of the Fixed-Precision
|
||||
// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
|
||||
// https://fmt.dev/papers/p372-steele.pdf.
|
||||
FMT_CONSTEXPR20 inline void format_dragon(basic_fp<uint128_t> value,
|
||||
unsigned flags, int num_digits,
|
||||
buffer<char>& buf, int& exp10) {
|
||||
bigint numerator; // 2 * R in (FPP)^2.
|
||||
bigint denominator; // 2 * S in (FPP)^2.
|
||||
// lower and upper are differences between value and corresponding boundaries.
|
||||
bigint lower; // (M^- in (FPP)^2).
|
||||
bigint upper_store; // upper's value if different from lower.
|
||||
bigint* upper = nullptr; // (M^+ in (FPP)^2).
|
||||
// Shift numerator and denominator by an extra bit or two (if lower boundary
|
||||
// is closer) to make lower and upper integers. This eliminates multiplication
|
||||
// by 2 during later computations.
|
||||
bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
|
||||
int shift = is_predecessor_closer ? 2 : 1;
|
||||
if (value.e >= 0) {
|
||||
numerator = value.f;
|
||||
numerator <<= value.e + shift;
|
||||
lower = 1;
|
||||
lower <<= value.e;
|
||||
if (is_predecessor_closer) {
|
||||
upper_store = 1;
|
||||
upper_store <<= value.e + 1;
|
||||
upper = &upper_store;
|
||||
}
|
||||
denominator.assign_pow10(exp10);
|
||||
denominator <<= shift;
|
||||
} else if (exp10 < 0) {
|
||||
numerator.assign_pow10(-exp10);
|
||||
lower.assign(numerator);
|
||||
if (is_predecessor_closer) {
|
||||
upper_store.assign(numerator);
|
||||
upper_store <<= 1;
|
||||
upper = &upper_store;
|
||||
}
|
||||
numerator *= value.f;
|
||||
numerator <<= shift;
|
||||
denominator = 1;
|
||||
denominator <<= shift - value.e;
|
||||
} else {
|
||||
numerator = value.f;
|
||||
numerator <<= shift;
|
||||
denominator.assign_pow10(exp10);
|
||||
denominator <<= shift - value.e;
|
||||
lower = 1;
|
||||
if (is_predecessor_closer) {
|
||||
upper_store = 1ULL << 1;
|
||||
upper = &upper_store;
|
||||
}
|
||||
}
|
||||
bool even = (value.f & 1) == 0;
|
||||
if (!upper) upper = &lower;
|
||||
if ((flags & dragon::fixup) != 0) {
|
||||
if (add_compare(numerator, *upper, denominator) + even <= 0) {
|
||||
--exp10;
|
||||
numerator *= 10;
|
||||
if (num_digits < 0) {
|
||||
lower *= 10;
|
||||
if (upper != &lower) *upper *= 10;
|
||||
}
|
||||
}
|
||||
if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1);
|
||||
}
|
||||
// Invariant: value == (numerator / denominator) * pow(10, exp10).
|
||||
if (num_digits < 0) {
|
||||
// Generate the shortest representation.
|
||||
num_digits = 0;
|
||||
char* data = buf.data();
|
||||
for (;;) {
|
||||
int digit = numerator.divmod_assign(denominator);
|
||||
bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower.
|
||||
// numerator + upper >[=] pow10:
|
||||
bool high = add_compare(numerator, *upper, denominator) + even > 0;
|
||||
data[num_digits++] = static_cast<char>('0' + digit);
|
||||
if (low || high) {
|
||||
if (!low) {
|
||||
++data[num_digits - 1];
|
||||
} else if (high) {
|
||||
int result = add_compare(numerator, numerator, denominator);
|
||||
// Round half to even.
|
||||
if (result > 0 || (result == 0 && (digit % 2) != 0))
|
||||
++data[num_digits - 1];
|
||||
}
|
||||
buf.try_resize(to_unsigned(num_digits));
|
||||
exp10 -= num_digits - 1;
|
||||
return;
|
||||
}
|
||||
numerator *= 10;
|
||||
lower *= 10;
|
||||
if (upper != &lower) *upper *= 10;
|
||||
}
|
||||
}
|
||||
// Generate the given number of digits.
|
||||
exp10 -= num_digits - 1;
|
||||
if (num_digits == 0) {
|
||||
denominator *= 10;
|
||||
auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
|
||||
buf.push_back(digit);
|
||||
return;
|
||||
}
|
||||
buf.try_resize(to_unsigned(num_digits));
|
||||
for (int i = 0; i < num_digits - 1; ++i) {
|
||||
int digit = numerator.divmod_assign(denominator);
|
||||
buf[i] = static_cast<char>('0' + digit);
|
||||
numerator *= 10;
|
||||
}
|
||||
int digit = numerator.divmod_assign(denominator);
|
||||
auto result = add_compare(numerator, numerator, denominator);
|
||||
if (result > 0 || (result == 0 && (digit % 2) != 0)) {
|
||||
if (digit == 9) {
|
||||
const auto overflow = '0' + 10;
|
||||
buf[num_digits - 1] = overflow;
|
||||
// Propagate the carry.
|
||||
for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
|
||||
buf[i] = '0';
|
||||
++buf[i - 1];
|
||||
}
|
||||
if (buf[0] == overflow) {
|
||||
buf[0] = '1';
|
||||
++exp10;
|
||||
}
|
||||
return;
|
||||
}
|
||||
++digit;
|
||||
}
|
||||
buf[num_digits - 1] = static_cast<char>('0' + digit);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
FMT_FUNC auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...)
|
||||
-> int {
|
||||
@ -2186,95 +1405,6 @@ FMT_FUNC auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Float>
|
||||
FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,
|
||||
float_specs specs,
|
||||
buffer<char>& buf) {
|
||||
// float is passed as double to reduce the number of instantiations.
|
||||
static_assert(!std::is_same<Float, float>::value, "");
|
||||
FMT_ASSERT(value >= 0, "value is negative");
|
||||
auto converted_value = convert_float(value);
|
||||
|
||||
const bool fixed = specs.format == float_format::fixed;
|
||||
if (value <= 0) { // <= instead of == to silence a warning.
|
||||
if (precision <= 0 || !fixed) {
|
||||
buf.push_back('0');
|
||||
return 0;
|
||||
}
|
||||
buf.try_resize(to_unsigned(precision));
|
||||
fill_n(buf.data(), precision, '0');
|
||||
return -precision;
|
||||
}
|
||||
|
||||
int exp = 0;
|
||||
bool use_dragon = true;
|
||||
unsigned dragon_flags = 0;
|
||||
if (!is_fast_float<Float>()) {
|
||||
const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10)
|
||||
using info = dragonbox::float_info<decltype(converted_value)>;
|
||||
const auto f = basic_fp<typename info::carrier_uint>(converted_value);
|
||||
// Compute exp, an approximate power of 10, such that
|
||||
// 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
|
||||
// This is based on log10(value) == log2(value) / log2(10) and approximation
|
||||
// of log2(value) by e + num_fraction_bits idea from double-conversion.
|
||||
exp = static_cast<int>(
|
||||
std::ceil((f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10));
|
||||
dragon_flags = dragon::fixup;
|
||||
} else if (!is_constant_evaluated() && precision < 0) {
|
||||
// Use Dragonbox for the shortest format.
|
||||
if (specs.binary32) {
|
||||
auto dec = dragonbox::to_decimal(static_cast<float>(value));
|
||||
write<char>(buffer_appender<char>(buf), dec.significand);
|
||||
return dec.exponent;
|
||||
}
|
||||
auto dec = dragonbox::to_decimal(static_cast<double>(value));
|
||||
write<char>(buffer_appender<char>(buf), dec.significand);
|
||||
return dec.exponent;
|
||||
} else {
|
||||
// Use Grisu + Dragon4 for the given precision:
|
||||
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
|
||||
const int min_exp = -60; // alpha in Grisu.
|
||||
int cached_exp10 = 0; // K in Grisu.
|
||||
fp normalized = normalize(fp(converted_value));
|
||||
const auto cached_pow = get_cached_power(
|
||||
min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
|
||||
normalized = normalized * cached_pow;
|
||||
gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
|
||||
if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
|
||||
!is_constant_evaluated()) {
|
||||
exp += handler.exp10;
|
||||
buf.try_resize(to_unsigned(handler.size));
|
||||
use_dragon = false;
|
||||
} else {
|
||||
exp += handler.size - cached_exp10 - 1;
|
||||
precision = handler.precision;
|
||||
}
|
||||
}
|
||||
if (use_dragon) {
|
||||
auto f = basic_fp<uint128_t>();
|
||||
bool is_predecessor_closer = specs.binary32
|
||||
? f.assign(static_cast<float>(value))
|
||||
: f.assign(converted_value);
|
||||
if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer;
|
||||
if (fixed) dragon_flags |= dragon::fixed;
|
||||
// Limit precision to the maximum possible number of significant digits in
|
||||
// an IEEE754 double because we don't need to generate zeros.
|
||||
const int max_double_digits = 767;
|
||||
if (precision > max_double_digits) precision = max_double_digits;
|
||||
format_dragon(f, dragon_flags, precision, buf, exp);
|
||||
}
|
||||
if (!fixed && !specs.showpoint) {
|
||||
// Remove trailing zeros.
|
||||
auto num_digits = buf.size();
|
||||
while (num_digits > 0 && buf[num_digits - 1] == '0') {
|
||||
--num_digits;
|
||||
++exp;
|
||||
}
|
||||
buf.try_resize(num_digits);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <> struct formatter<detail::bigint> {
|
||||
@ -2335,12 +1465,6 @@ FMT_FUNC void report_system_error(int error_code,
|
||||
report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
// DEPRECATED!
|
||||
// This function is defined here and not inline for ABI compatiblity.
|
||||
FMT_FUNC void detail::error_handler::on_error(const char* message) {
|
||||
throw_format_error(message);
|
||||
}
|
||||
|
||||
FMT_FUNC std::string vformat(string_view fmt, format_args args) {
|
||||
// Don't optimize the "{}" case to keep the binary size small and because it
|
||||
// can be better optimized in fmt::format anyway.
|
||||
@ -2349,17 +1473,13 @@ FMT_FUNC std::string vformat(string_view fmt, format_args args) {
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace detail {
|
||||
#ifdef _WIN32
|
||||
using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>;
|
||||
extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( //
|
||||
void*, const void*, dword, dword*, void*);
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
FMT_FUNC void print(std::FILE* f, string_view text) {
|
||||
#ifdef _WIN32
|
||||
FMT_FUNC bool write_console(std::FILE* f, string_view text) {
|
||||
auto fd = _fileno(f);
|
||||
if (_isatty(fd)) {
|
||||
detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));
|
||||
@ -2367,11 +1487,20 @@ FMT_FUNC void print(std::FILE* f, string_view text) {
|
||||
if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
|
||||
u16.c_str(), static_cast<uint32_t>(u16.size()),
|
||||
&written, nullptr)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
// Fallback to fwrite on failure. It can happen if the output has been
|
||||
// redirected to NUL.
|
||||
}
|
||||
// We return false if the file descriptor was not TTY, or it was but
|
||||
// SetConsoleW failed which can happen if the output has been redirected to
|
||||
// NUL. In both cases when we return false, we should attempt to do regular
|
||||
// write via fwrite or std::ostream::write.
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_FUNC void print(std::FILE* f, string_view text) {
|
||||
#ifdef _WIN32
|
||||
if (write_console(f, text)) return;
|
||||
#endif
|
||||
detail::fwrite_fully(text.data(), 1, text.size(), f);
|
||||
}
|
||||
|
1295
Externals/fmt/include/fmt/format.h
vendored
1295
Externals/fmt/include/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
2
Externals/fmt/include/fmt/locale.h
vendored
2
Externals/fmt/include/fmt/locale.h
vendored
@ -1,2 +0,0 @@
|
||||
#include "xchar.h"
|
||||
#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead
|
5
Externals/fmt/include/fmt/os.h
vendored
5
Externals/fmt/include/fmt/os.h
vendored
@ -260,10 +260,7 @@ class buffered_file {
|
||||
// Returns the pointer to a FILE object representing this file.
|
||||
FILE* get() const noexcept { return file_; }
|
||||
|
||||
// We place parentheses around fileno to workaround a bug in some versions
|
||||
// of MinGW that define fileno as a macro.
|
||||
// DEPRECATED! Rename to descriptor to avoid issues with macros.
|
||||
FMT_API int(fileno)() const;
|
||||
FMT_API int descriptor() const;
|
||||
|
||||
void vprint(string_view format_str, format_args args) {
|
||||
fmt::vprint(file_, format_str, args);
|
||||
|
134
Externals/fmt/include/fmt/ostream.h
vendored
134
Externals/fmt/include/fmt/ostream.h
vendored
@ -10,6 +10,12 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
#if defined(_WIN32) && defined(__GLIBCXX__)
|
||||
# include <ext/stdio_filebuf.h>
|
||||
# include <ext/stdio_sync_filebuf.h>
|
||||
#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
|
||||
# include <__std_stream>
|
||||
#endif
|
||||
|
||||
#include "format.h"
|
||||
|
||||
@ -51,41 +57,50 @@ struct is_streamable<
|
||||
(std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
|
||||
: std::false_type {};
|
||||
|
||||
template <typename Char> FILE* get_file(std::basic_filebuf<Char>&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct dummy_filebuf {
|
||||
FILE* _Myfile;
|
||||
};
|
||||
template <typename T, typename U = int> struct ms_filebuf {
|
||||
using type = dummy_filebuf;
|
||||
};
|
||||
template <typename T> struct ms_filebuf<T, decltype(T::_Myfile, 0)> {
|
||||
using type = T;
|
||||
};
|
||||
using filebuf_type = ms_filebuf<std::filebuf>::type;
|
||||
|
||||
FILE* get_file(filebuf_type& buf);
|
||||
|
||||
// Generate a unique explicit instantion in every translation unit using a tag
|
||||
// type in an anonymous namespace.
|
||||
namespace {
|
||||
struct filebuf_access_tag {};
|
||||
struct file_access_tag {};
|
||||
} // namespace
|
||||
template <typename Tag, typename FileMemberPtr, FileMemberPtr file>
|
||||
class filebuf_access {
|
||||
friend FILE* get_file(filebuf_type& buf) { return buf.*file; }
|
||||
template <class Tag, class BufType, FILE* BufType::*FileMemberPtr>
|
||||
class file_access {
|
||||
friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
|
||||
};
|
||||
template class filebuf_access<filebuf_access_tag,
|
||||
decltype(&filebuf_type::_Myfile),
|
||||
&filebuf_type::_Myfile>;
|
||||
|
||||
inline bool write(std::filebuf& buf, fmt::string_view data) {
|
||||
print(get_file(buf), data);
|
||||
return true;
|
||||
#if FMT_MSC_VERSION
|
||||
template class file_access<file_access_tag, std::filebuf,
|
||||
&std::filebuf::_Myfile>;
|
||||
auto get_file(std::filebuf&) -> FILE*;
|
||||
#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
|
||||
template class file_access<file_access_tag, std::__stdoutbuf<char>,
|
||||
&std::__stdoutbuf<char>::__file_>;
|
||||
auto get_file(std::__stdoutbuf<char>&) -> FILE*;
|
||||
#endif
|
||||
|
||||
inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) {
|
||||
#if FMT_MSC_VERSION
|
||||
if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
|
||||
if (FILE* f = get_file(*buf)) return write_console(f, data);
|
||||
#elif defined(_WIN32) && defined(__GLIBCXX__)
|
||||
auto* rdbuf = os.rdbuf();
|
||||
FILE* c_file;
|
||||
if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
|
||||
c_file = fbuf->file();
|
||||
else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
|
||||
c_file = fbuf->file();
|
||||
else
|
||||
return false;
|
||||
if (c_file) return write_console(c_file, data);
|
||||
#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
|
||||
if (auto* buf = dynamic_cast<std::__stdoutbuf<char>*>(os.rdbuf()))
|
||||
if (FILE* f = get_file(*buf)) return write_console(f, data);
|
||||
#else
|
||||
ignore_unused(os, data);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) {
|
||||
inline bool write_ostream_unicode(std::wostream&,
|
||||
fmt::basic_string_view<wchar_t>) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -93,10 +108,6 @@ inline bool write(std::wfilebuf&, fmt::basic_string_view<wchar_t>) {
|
||||
// It is a separate function rather than a part of vprint to simplify testing.
|
||||
template <typename Char>
|
||||
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
||||
if (const_check(FMT_MSC_VER)) {
|
||||
auto filebuf = dynamic_cast<std::basic_filebuf<Char>*>(os.rdbuf());
|
||||
if (filebuf && write(*filebuf, {buf.data(), buf.size()})) return;
|
||||
}
|
||||
const Char* buf_data = buf.data();
|
||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||
unsigned_streamsize size = buf.size();
|
||||
@ -120,11 +131,16 @@ void format_value(buffer<Char>& buf, const T& value,
|
||||
output << value;
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
}
|
||||
|
||||
template <typename T> struct streamed_view { const T& value; };
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
template <typename Char>
|
||||
struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
|
||||
void set_debug_format() = delete;
|
||||
|
||||
template <typename T, typename OutputIt>
|
||||
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
|
||||
-> OutputIt {
|
||||
@ -137,6 +153,31 @@ struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
|
||||
|
||||
using ostream_formatter = basic_ostream_formatter<char>;
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<detail::streamed_view<T>, Char>
|
||||
: basic_ostream_formatter<Char> {
|
||||
template <typename OutputIt>
|
||||
auto format(detail::streamed_view<T> view,
|
||||
basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
|
||||
return basic_ostream_formatter<Char>::format(view.value, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\rst
|
||||
Returns a view that formats `value` via an ostream ``operator<<``.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::print("Current thread id: {}\n",
|
||||
fmt::streamed(std::this_thread::get_id()));
|
||||
\endrst
|
||||
*/
|
||||
template <typename T>
|
||||
auto streamed(const T& value) -> detail::streamed_view<T> {
|
||||
return {value};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
@ -144,24 +185,24 @@ template <typename T, typename Char>
|
||||
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
||||
: basic_ostream_formatter<Char> {
|
||||
using basic_ostream_formatter<Char>::format;
|
||||
// DEPRECATED!
|
||||
template <typename OutputIt>
|
||||
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx) const
|
||||
-> OutputIt {
|
||||
auto buffer = basic_memory_buffer<Char>();
|
||||
format_value(buffer, value, ctx.locale());
|
||||
return std::copy(buffer.begin(), buffer.end(), ctx.out());
|
||||
}
|
||||
};
|
||||
|
||||
inline void vprint_directly(std::ostream& os, string_view format_str,
|
||||
format_args args) {
|
||||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_MODULE_EXPORT
|
||||
template <typename Char>
|
||||
FMT_MODULE_EXPORT template <typename Char>
|
||||
void vprint(std::basic_ostream<Char>& os,
|
||||
basic_string_view<type_identity_t<Char>> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
auto buffer = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
@ -174,10 +215,13 @@ void vprint(std::basic_ostream<Char>& os,
|
||||
fmt::print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_MODULE_EXPORT
|
||||
template <typename... T>
|
||||
FMT_MODULE_EXPORT template <typename... T>
|
||||
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
||||
vprint(os, fmt, fmt::make_format_args(args...));
|
||||
const auto& vargs = fmt::make_format_args(args...);
|
||||
if (detail::is_utf8())
|
||||
vprint(os, fmt, vargs);
|
||||
else
|
||||
detail::vprint_directly(os, fmt, vargs);
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT
|
||||
|
31
Externals/fmt/include/fmt/printf.h
vendored
31
Externals/fmt/include/fmt/printf.h
vendored
@ -10,7 +10,6 @@
|
||||
|
||||
#include <algorithm> // std::max
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <ostream>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
@ -561,7 +560,7 @@ inline auto vsprintf(
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> std::basic_string<Char> {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
vprintf(buffer, detail::to_string_view(fmt), args);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@ -578,7 +577,8 @@ template <typename S, typename... T,
|
||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...));
|
||||
return vsprintf(detail::to_string_view(fmt),
|
||||
fmt::make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
@ -587,7 +587,7 @@ inline auto vfprintf(
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
vprintf(buffer, detail::to_string_view(fmt), args);
|
||||
size_t size = buffer.size();
|
||||
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
||||
? -1
|
||||
@ -606,7 +606,7 @@ inline auto vfprintf(
|
||||
template <typename S, typename... T, typename Char = char_t<S>>
|
||||
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(f, to_string_view(fmt),
|
||||
return vfprintf(f, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ inline auto vprintf(
|
||||
const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
return vfprintf(stdout, to_string_view(fmt), args);
|
||||
return vfprintf(stdout, detail::to_string_view(fmt), args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -630,27 +630,10 @@ inline auto vprintf(
|
||||
template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
inline auto printf(const S& fmt, const T&... args) -> int {
|
||||
return vprintf(
|
||||
to_string_view(fmt),
|
||||
detail::to_string_view(fmt),
|
||||
fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
FMT_DEPRECATED auto vfprintf(
|
||||
std::basic_ostream<Char>& os, const S& fmt,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||
-> int {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
vprintf(buffer, to_string_view(fmt), args);
|
||||
os.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
|
||||
return static_cast<int>(buffer.size());
|
||||
}
|
||||
template <typename S, typename... T, typename Char = char_t<S>>
|
||||
FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt,
|
||||
const T&... args) -> int {
|
||||
return vfprintf(os, to_string_view(fmt),
|
||||
fmt::make_format_args<basic_printf_context_t<Char>>(args...));
|
||||
}
|
||||
|
||||
FMT_MODULE_EXPORT_END
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
|
316
Externals/fmt/include/fmt/ranges.h
vendored
316
Externals/fmt/include/fmt/ranges.h
vendored
@ -55,7 +55,7 @@ template <typename T> class is_std_string_like {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
is_string<T>::value ||
|
||||
std::is_convertible<T, std_string_view<char>>::value ||
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
@ -70,9 +70,9 @@ template <typename T> class is_map {
|
||||
|
||||
public:
|
||||
#ifdef FMT_FORMAT_MAP_AS_LIST
|
||||
static FMT_CONSTEXPR_DECL const bool value = false;
|
||||
static constexpr const bool value = false;
|
||||
#else
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
#endif
|
||||
};
|
||||
@ -83,9 +83,9 @@ template <typename T> class is_set {
|
||||
|
||||
public:
|
||||
#ifdef FMT_FORMAT_SET_AS_LIST
|
||||
static FMT_CONSTEXPR_DECL const bool value = false;
|
||||
static constexpr const bool value = false;
|
||||
#else
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
|
||||
#endif
|
||||
};
|
||||
@ -94,7 +94,7 @@ template <typename... Ts> struct conditional_helper {};
|
||||
|
||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
||||
|
||||
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
|
||||
|
||||
# define FMT_DECLTYPE_RETURN(val) \
|
||||
->decltype(val) { return val; } \
|
||||
@ -174,12 +174,12 @@ template <typename T> class is_tuple_like_ {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
// Check for integer_sequence
|
||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
|
||||
template <typename T, T... N>
|
||||
using integer_sequence = std::integer_sequence<T, N...>;
|
||||
template <size_t... N> using index_sequence = std::index_sequence<N...>;
|
||||
@ -202,6 +202,31 @@ template <size_t N>
|
||||
using make_index_sequence = make_integer_sequence<size_t, N>;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
|
||||
|
||||
template <typename T, typename C, bool = is_tuple_like_<T>::value>
|
||||
class is_tuple_formattable_ {
|
||||
public:
|
||||
static constexpr const bool value = false;
|
||||
};
|
||||
template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
|
||||
template <std::size_t... I>
|
||||
static std::true_type check2(index_sequence<I...>,
|
||||
integer_sequence<bool, (I == I)...>);
|
||||
static std::false_type check2(...);
|
||||
template <std::size_t... I>
|
||||
static decltype(check2(
|
||||
index_sequence<I...>{},
|
||||
integer_sequence<
|
||||
bool, (is_formattable<typename std::tuple_element<I, T>::type,
|
||||
C>::value)...>{})) check(index_sequence<I...>);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
decltype(check(tuple_index_sequence<T>{}))::value;
|
||||
};
|
||||
|
||||
template <class Tuple, class F, size_t... Is>
|
||||
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
|
||||
using std::get;
|
||||
@ -221,7 +246,7 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||
}
|
||||
|
||||
#if FMT_MSC_VER
|
||||
#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
|
||||
// Older MSVC doesn't get the reference type correctly for arrays.
|
||||
template <typename R> struct range_reference_type_impl {
|
||||
using type = decltype(*detail::range_begin(std::declval<R&>()));
|
||||
@ -244,6 +269,14 @@ using range_reference_type =
|
||||
template <typename Range>
|
||||
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
|
||||
|
||||
template <typename Range>
|
||||
using uncvref_first_type =
|
||||
remove_cvref_t<decltype(std::declval<range_reference_type<Range>>().first)>;
|
||||
|
||||
template <typename Range>
|
||||
using uncvref_second_type = remove_cvref_t<
|
||||
decltype(std::declval<range_reference_type<Range>>().second)>;
|
||||
|
||||
template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
|
||||
*out++ = ',';
|
||||
*out++ = ' ';
|
||||
@ -279,25 +312,51 @@ OutputIt write_range_entry(OutputIt out, const Arg& v) {
|
||||
} // namespace detail
|
||||
|
||||
template <typename T> struct is_tuple_like {
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename C> struct is_tuple_formattable {
|
||||
static constexpr const bool value =
|
||||
detail::is_tuple_formattable_<T, C>::value;
|
||||
};
|
||||
|
||||
template <typename TupleT, typename Char>
|
||||
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
||||
struct formatter<TupleT, Char,
|
||||
enable_if_t<fmt::is_tuple_like<TupleT>::value &&
|
||||
fmt::is_tuple_formattable<TupleT, Char>::value>> {
|
||||
private:
|
||||
basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
|
||||
basic_string_view<Char> opening_bracket_ =
|
||||
detail::string_literal<Char, '('>{};
|
||||
basic_string_view<Char> closing_bracket_ =
|
||||
detail::string_literal<Char, ')'>{};
|
||||
|
||||
// C++11 generic lambda for format().
|
||||
template <typename FormatContext> struct format_each {
|
||||
template <typename T> void operator()(const T& v) {
|
||||
if (i > 0) out = detail::write_delimiter(out);
|
||||
if (i > 0) out = detail::copy_str<Char>(separator, out);
|
||||
out = detail::write_range_entry<Char>(out, v);
|
||||
++i;
|
||||
}
|
||||
int i;
|
||||
typename FormatContext::iterator& out;
|
||||
basic_string_view<Char> separator;
|
||||
};
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR formatter() {}
|
||||
|
||||
FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
|
||||
separator_ = sep;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
|
||||
basic_string_view<Char> close) {
|
||||
opening_bracket_ = open;
|
||||
closing_bracket_ = close;
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
@ -307,19 +366,18 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
||||
auto format(const TupleT& values, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
*out++ = '(';
|
||||
detail::for_each(values, format_each<FormatContext>{0, out});
|
||||
*out++ = ')';
|
||||
out = detail::copy_str<Char>(opening_bracket_, out);
|
||||
detail::for_each(values, format_each<FormatContext>{0, out, separator_});
|
||||
out = detail::copy_str<Char>(closing_bracket_, out);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Char> struct is_range {
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
static constexpr const bool value =
|
||||
detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
|
||||
!detail::is_map<T>::value &&
|
||||
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
||||
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
||||
!std::is_convertible<T, detail::std_string_view<Char>>::value;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@ -350,37 +408,88 @@ using range_formatter_type = conditional_t<
|
||||
template <typename R>
|
||||
using maybe_const_range =
|
||||
conditional_t<has_const_begin_end<R>::value, const R, R>;
|
||||
|
||||
// Workaround a bug in MSVC 2015 and earlier.
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
||||
template <typename R, typename Char>
|
||||
struct is_formattable_delayed
|
||||
: disjunction<
|
||||
is_formattable<uncvref_type<maybe_const_range<R>>, Char>,
|
||||
has_fallback_formatter<uncvref_type<maybe_const_range<R>>, Char>> {};
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename R, typename Char>
|
||||
struct formatter<
|
||||
R, Char,
|
||||
enable_if_t<
|
||||
fmt::is_range<R, Char>::value
|
||||
// Workaround a bug in MSVC 2019 and earlier.
|
||||
#if !FMT_MSC_VER
|
||||
&&
|
||||
(is_formattable<detail::uncvref_type<detail::maybe_const_range<R>>,
|
||||
Char>::value ||
|
||||
detail::has_fallback_formatter<
|
||||
detail::uncvref_type<detail::maybe_const_range<R>>, Char>::value)
|
||||
#endif
|
||||
>> {
|
||||
template <typename T, typename Char, typename Enable = void>
|
||||
struct range_formatter;
|
||||
|
||||
using range_type = detail::maybe_const_range<R>;
|
||||
using formatter_type =
|
||||
detail::range_formatter_type<Char, detail::uncvref_type<range_type>>;
|
||||
formatter_type underlying_;
|
||||
template <typename T, typename Char>
|
||||
struct range_formatter<
|
||||
T, Char,
|
||||
enable_if_t<conjunction<
|
||||
std::is_same<T, remove_cvref_t<T>>,
|
||||
disjunction<is_formattable<T, Char>,
|
||||
detail::has_fallback_formatter<T, Char>>>::value>> {
|
||||
private:
|
||||
detail::range_formatter_type<Char, T> underlying_;
|
||||
bool custom_specs_ = false;
|
||||
basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
|
||||
basic_string_view<Char> opening_bracket_ =
|
||||
detail::string_literal<Char, '['>{};
|
||||
basic_string_view<Char> closing_bracket_ =
|
||||
detail::string_literal<Char, ']'>{};
|
||||
|
||||
template <class U>
|
||||
FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, int)
|
||||
-> decltype(u.set_debug_format()) {
|
||||
u.set_debug_format();
|
||||
}
|
||||
|
||||
template <class U>
|
||||
FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
|
||||
|
||||
FMT_CONSTEXPR void maybe_set_debug_format() {
|
||||
maybe_set_debug_format(underlying_, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR range_formatter() {}
|
||||
|
||||
FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
|
||||
return underlying_;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
|
||||
separator_ = sep;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
|
||||
basic_string_view<Char> close) {
|
||||
opening_bracket_ = open;
|
||||
closing_bracket_ = close;
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
if (it == end || *it == '}') return it;
|
||||
if (it == end || *it == '}') {
|
||||
maybe_set_debug_format();
|
||||
return it;
|
||||
}
|
||||
|
||||
if (*it == 'n') {
|
||||
set_brackets({}, {});
|
||||
++it;
|
||||
}
|
||||
|
||||
if (*it == '}') {
|
||||
maybe_set_debug_format();
|
||||
return it;
|
||||
}
|
||||
|
||||
if (*it != ':')
|
||||
FMT_THROW(format_error("no top-level range formatters supported"));
|
||||
FMT_THROW(format_error("no other top-level range formatters supported"));
|
||||
|
||||
custom_specs_ = true;
|
||||
++it;
|
||||
@ -388,73 +497,100 @@ struct formatter<
|
||||
return underlying_.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
#ifdef FMT_DEPRECATED_BRACED_RANGES
|
||||
Char prefix = '{';
|
||||
Char postfix = '}';
|
||||
#else
|
||||
Char prefix = detail::is_set<R>::value ? '{' : '[';
|
||||
Char postfix = detail::is_set<R>::value ? '}' : ']';
|
||||
#endif
|
||||
template <typename R, class FormatContext>
|
||||
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
detail::range_mapper<buffer_context<Char>> mapper;
|
||||
auto out = ctx.out();
|
||||
*out++ = prefix;
|
||||
out = detail::copy_str<Char>(opening_bracket_, out);
|
||||
int i = 0;
|
||||
auto it = detail::range_begin(range);
|
||||
auto end = detail::range_end(range);
|
||||
for (; it != end; ++it) {
|
||||
if (i > 0) out = detail::write_delimiter(out);
|
||||
if (custom_specs_) {
|
||||
ctx.advance_to(out);
|
||||
out = underlying_.format(mapper.map(*it), ctx);
|
||||
} else {
|
||||
out = detail::write_range_entry<Char>(out, *it);
|
||||
}
|
||||
if (i > 0) out = detail::copy_str<Char>(separator_, out);
|
||||
;
|
||||
ctx.advance_to(out);
|
||||
out = underlying_.format(mapper.map(*it), ctx);
|
||||
++i;
|
||||
}
|
||||
*out++ = postfix;
|
||||
out = detail::copy_str<Char>(closing_bracket_, out);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<
|
||||
T, Char,
|
||||
enable_if_t<detail::is_map<T>::value
|
||||
// Workaround a bug in MSVC 2019 and earlier.
|
||||
#if !FMT_MSC_VER
|
||||
&& (is_formattable<detail::uncvref_type<T>, Char>::value ||
|
||||
detail::has_fallback_formatter<detail::uncvref_type<T>,
|
||||
Char>::value)
|
||||
#endif
|
||||
>> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
enum class range_format { disabled, map, set, sequence, string, debug_string };
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct range_format_kind_ {
|
||||
static constexpr auto value = std::is_same<range_reference_type<T>, T>::value
|
||||
? range_format::disabled
|
||||
: is_map<T>::value ? range_format::map
|
||||
: is_set<T>::value ? range_format::set
|
||||
: range_format::sequence;
|
||||
};
|
||||
|
||||
template <range_format K, typename R, typename Char, typename Enable = void>
|
||||
struct range_default_formatter;
|
||||
|
||||
template <range_format K>
|
||||
using range_format_constant = std::integral_constant<range_format, K>;
|
||||
|
||||
template <range_format K, typename R, typename Char>
|
||||
struct range_default_formatter<
|
||||
K, R, Char,
|
||||
enable_if_t<(K == range_format::sequence || K == range_format::map ||
|
||||
K == range_format::set)>> {
|
||||
using range_type = detail::maybe_const_range<R>;
|
||||
range_formatter<detail::uncvref_type<range_type>, Char> underlying_;
|
||||
|
||||
FMT_CONSTEXPR range_default_formatter() { init(range_format_constant<K>()); }
|
||||
|
||||
FMT_CONSTEXPR void init(range_format_constant<range_format::set>) {
|
||||
underlying_.set_brackets(detail::string_literal<Char, '{'>{},
|
||||
detail::string_literal<Char, '}'>{});
|
||||
}
|
||||
|
||||
template <
|
||||
typename FormatContext, typename U,
|
||||
FMT_ENABLE_IF(
|
||||
std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
|
||||
const T, T>>::value)>
|
||||
auto format(U& map, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
*out++ = '{';
|
||||
int i = 0;
|
||||
for (const auto& item : map) {
|
||||
if (i > 0) out = detail::write_delimiter(out);
|
||||
out = detail::write_range_entry<Char>(out, item.first);
|
||||
*out++ = ':';
|
||||
*out++ = ' ';
|
||||
out = detail::write_range_entry<Char>(out, item.second);
|
||||
++i;
|
||||
}
|
||||
*out++ = '}';
|
||||
return out;
|
||||
FMT_CONSTEXPR void init(range_format_constant<range_format::map>) {
|
||||
underlying_.set_brackets(detail::string_literal<Char, '{'>{},
|
||||
detail::string_literal<Char, '}'>{});
|
||||
underlying_.underlying().set_brackets({}, {});
|
||||
underlying_.underlying().set_separator(
|
||||
detail::string_literal<Char, ':', ' '>{});
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void init(range_format_constant<range_format::sequence>) {}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return underlying_.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return underlying_.format(range, ctx);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename Char, typename Enable = void>
|
||||
struct range_format_kind
|
||||
: conditional_t<
|
||||
is_range<T, Char>::value, detail::range_format_kind_<T>,
|
||||
std::integral_constant<range_format, range_format::disabled>> {};
|
||||
|
||||
template <typename R, typename Char>
|
||||
struct formatter<
|
||||
R, Char,
|
||||
enable_if_t<conjunction<bool_constant<range_format_kind<R, Char>::value !=
|
||||
range_format::disabled>
|
||||
// Workaround a bug in MSVC 2015 and earlier.
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
||||
,
|
||||
detail::is_formattable_delayed<R, Char>
|
||||
#endif
|
||||
>::value>>
|
||||
: detail::range_default_formatter<range_format_kind<R, Char>::value, R,
|
||||
Char> {
|
||||
};
|
||||
|
||||
template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
||||
|
171
Externals/fmt/include/fmt/std.h
vendored
Normal file
171
Externals/fmt/include/fmt/std.h
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
// Formatting library for C++ - formatters for standard library types
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_STD_H_
|
||||
#define FMT_STD_H_
|
||||
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "ostream.h"
|
||||
|
||||
#if FMT_HAS_INCLUDE(<version>)
|
||||
# include <version>
|
||||
#endif
|
||||
// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
|
||||
#if FMT_CPLUSPLUS >= 201703L
|
||||
# if FMT_HAS_INCLUDE(<filesystem>)
|
||||
# include <filesystem>
|
||||
# endif
|
||||
# if FMT_HAS_INCLUDE(<variant>)
|
||||
# include <variant>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_lib_filesystem
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Char>
|
||||
void write_escaped_path(basic_memory_buffer<Char>& quoted,
|
||||
const std::filesystem::path& p) {
|
||||
write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
|
||||
}
|
||||
# ifdef _WIN32
|
||||
template <>
|
||||
inline void write_escaped_path<char>(basic_memory_buffer<char>& quoted,
|
||||
const std::filesystem::path& p) {
|
||||
auto s = p.u8string();
|
||||
write_escaped_string<char>(
|
||||
std::back_inserter(quoted),
|
||||
string_view(reinterpret_cast<const char*>(s.c_str()), s.size()));
|
||||
}
|
||||
# endif
|
||||
template <>
|
||||
inline void write_escaped_path<std::filesystem::path::value_type>(
|
||||
basic_memory_buffer<std::filesystem::path::value_type>& quoted,
|
||||
const std::filesystem::path& p) {
|
||||
write_escaped_string<std::filesystem::path::value_type>(
|
||||
std::back_inserter(quoted), p.native());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<std::filesystem::path, Char>
|
||||
: formatter<basic_string_view<Char>> {
|
||||
template <typename FormatContext>
|
||||
auto format(const std::filesystem::path& p, FormatContext& ctx) const ->
|
||||
typename FormatContext::iterator {
|
||||
basic_memory_buffer<Char> quoted;
|
||||
detail::write_escaped_path(quoted, p);
|
||||
return formatter<basic_string_view<Char>>::format(
|
||||
basic_string_view<Char>(quoted.data(), quoted.size()), ctx);
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <typename Char>
|
||||
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#ifdef __cpp_lib_variant
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <typename Char> struct formatter<std::monostate, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::monostate&, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
out = detail::write<Char>(out, "monostate");
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
using variant_index_sequence =
|
||||
std::make_index_sequence<std::variant_size<T>::value>;
|
||||
|
||||
// variant_size and variant_alternative check.
|
||||
template <typename T, typename U = void>
|
||||
struct is_variant_like_ : std::false_type {};
|
||||
template <typename T>
|
||||
struct is_variant_like_<T, std::void_t<decltype(std::variant_size<T>::value)>>
|
||||
: std::true_type {};
|
||||
|
||||
// formattable element check
|
||||
template <typename T, typename C> class is_variant_formattable_ {
|
||||
template <std::size_t... I>
|
||||
static std::conjunction<
|
||||
is_formattable<std::variant_alternative_t<I, T>, C>...>
|
||||
check(std::index_sequence<I...>);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
decltype(check(variant_index_sequence<T>{}))::value;
|
||||
};
|
||||
|
||||
template <typename Char, typename OutputIt, typename T>
|
||||
auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt {
|
||||
if constexpr (is_string<T>::value)
|
||||
return write_escaped_string<Char>(out, detail::to_string_view(v));
|
||||
else if constexpr (std::is_same_v<T, Char>)
|
||||
return write_escaped_char(out, v);
|
||||
else
|
||||
return write<Char>(out, v);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T> struct is_variant_like {
|
||||
static constexpr const bool value = detail::is_variant_like_<T>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename C> struct is_variant_formattable {
|
||||
static constexpr const bool value =
|
||||
detail::is_variant_formattable_<T, C>::value;
|
||||
};
|
||||
|
||||
template <typename Variant, typename Char>
|
||||
struct formatter<
|
||||
Variant, Char,
|
||||
std::enable_if_t<std::conjunction_v<
|
||||
is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Variant& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
|
||||
out = detail::write<Char>(out, "variant(");
|
||||
std::visit(
|
||||
[&](const auto& v) {
|
||||
out = detail::write_variant_alternative<Char>(out, v);
|
||||
},
|
||||
value);
|
||||
*out++ = ')';
|
||||
return out;
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
#endif // FMT_STD_H_
|
45
Externals/fmt/include/fmt/xchar.h
vendored
45
Externals/fmt/include/fmt/xchar.h
vendored
@ -9,7 +9,6 @@
|
||||
#define FMT_XCHAR_H_
|
||||
|
||||
#include <cwchar>
|
||||
#include <tuple>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
@ -30,9 +29,11 @@ using wmemory_buffer = basic_memory_buffer<wchar_t>;
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
// Workaround broken conversion on older gcc.
|
||||
template <typename... Args> using wformat_string = wstring_view;
|
||||
inline auto runtime(wstring_view s) -> wstring_view { return s; }
|
||||
#else
|
||||
template <typename... Args>
|
||||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
|
||||
inline auto runtime(wstring_view s) -> basic_runtime<wchar_t> { return {{s}}; }
|
||||
#endif
|
||||
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
@ -47,12 +48,7 @@ constexpr format_arg_store<wformat_context, Args...> make_wformat_args(
|
||||
}
|
||||
|
||||
inline namespace literals {
|
||||
constexpr auto operator"" _format(const wchar_t* s, size_t n)
|
||||
-> detail::udl_formatter<wchar_t> {
|
||||
return {{s, n}};
|
||||
}
|
||||
|
||||
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
|
||||
return {s};
|
||||
}
|
||||
@ -87,12 +83,18 @@ auto vformat(basic_string_view<Char> format_str,
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
|
||||
return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
// Pass char_t as a default template parameter instead of using
|
||||
// std::basic_string<char_t<S>> to reduce the symbol size.
|
||||
template <typename S, typename... Args, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
|
||||
!std::is_same<Char, wchar_t>::value)>
|
||||
auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
|
||||
return vformat(to_string_view(format_str),
|
||||
return vformat(detail::to_string_view(format_str),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -103,7 +105,7 @@ inline auto vformat(
|
||||
const Locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(loc, to_string_view(format_str), args);
|
||||
return detail::vformat(loc, detail::to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename... Args,
|
||||
@ -112,7 +114,7 @@ template <typename Locale, typename S, typename... Args,
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format(const Locale& loc, const S& format_str, Args&&... args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(loc, to_string_view(format_str),
|
||||
return detail::vformat(loc, detail::to_string_view(format_str),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -123,7 +125,7 @@ auto vformat_to(OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, to_string_view(format_str), args);
|
||||
detail::vformat_to(buf, detail::to_string_view(format_str), args);
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
@ -132,20 +134,10 @@ template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
|
||||
return vformat_to(out, to_string_view(fmt),
|
||||
return vformat_to(out, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename... Args, typename Char, size_t SIZE,
|
||||
typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
|
||||
const S& format_str, Args&&... args) ->
|
||||
typename buffer_context<Char>::iterator {
|
||||
detail::vformat_to(buf, to_string_view(format_str),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...), {});
|
||||
return detail::buffer_appender<Char>(buf);
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename OutputIt, typename... Args,
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
@ -155,7 +147,8 @@ inline auto vformat_to(
|
||||
OutputIt out, const Locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
|
||||
vformat_to(buf, detail::to_string_view(format_str), args,
|
||||
detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
@ -190,7 +183,7 @@ template <typename OutputIt, typename S, typename... Args,
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
|
||||
const Args&... args) -> format_to_n_result<OutputIt> {
|
||||
return vformat_to_n(out, n, to_string_view(fmt),
|
||||
return vformat_to_n(out, n, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
}
|
||||
|
||||
@ -198,7 +191,7 @@ template <typename S, typename... Args, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||
inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
|
||||
detail::counting_buffer<Char> buf;
|
||||
detail::vformat_to(buf, to_string_view(fmt),
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffer_context<Char>>(args...));
|
||||
return buf.count();
|
||||
}
|
||||
|
90
Externals/fmt/src/format.cc
vendored
90
Externals/fmt/src/format.cc
vendored
@ -10,96 +10,38 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
// DEPRECATED!
|
||||
template <typename T = void> struct basic_data {
|
||||
FMT_API static constexpr const char digits[100][2] = {
|
||||
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
|
||||
{'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
|
||||
{'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
|
||||
{'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
|
||||
{'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
|
||||
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
|
||||
{'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
|
||||
{'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
|
||||
{'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
|
||||
{'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
|
||||
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
|
||||
{'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
|
||||
{'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
|
||||
{'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
|
||||
{'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
|
||||
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
|
||||
{'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
|
||||
FMT_API static constexpr const char hex_digits[] = "0123456789abcdef";
|
||||
FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};
|
||||
FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1,
|
||||
0};
|
||||
FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1,
|
||||
0};
|
||||
FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
|
||||
0x1000000u | ' '};
|
||||
};
|
||||
|
||||
#ifdef FMT_SHARED
|
||||
// Required for -flto, -fivisibility=hidden and -shared to work
|
||||
extern template struct basic_data<void>;
|
||||
#endif
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
// DEPRECATED! These are here only for ABI compatiblity.
|
||||
template <typename T> constexpr const char basic_data<T>::digits[][2];
|
||||
template <typename T> constexpr const char basic_data<T>::hex_digits[];
|
||||
template <typename T> constexpr const char basic_data<T>::signs[];
|
||||
template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
|
||||
template <typename T>
|
||||
constexpr const char basic_data<T>::right_padding_shifts[];
|
||||
template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
|
||||
#endif
|
||||
|
||||
template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(
|
||||
float x) noexcept;
|
||||
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(
|
||||
double x) noexcept;
|
||||
} // namespace detail
|
||||
|
||||
// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
|
||||
int (*instantiate_format_float)(double, int, detail::float_specs,
|
||||
detail::buffer<char>&) = detail::format_float;
|
||||
template FMT_API auto dragonbox::to_decimal(float x) noexcept
|
||||
-> dragonbox::decimal_fp<float>;
|
||||
template FMT_API auto dragonbox::to_decimal(double x) noexcept
|
||||
-> dragonbox::decimal_fp<double>;
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
|
||||
template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
|
||||
template FMT_API locale_ref::locale_ref(const std::locale& loc);
|
||||
template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
|
||||
#endif
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template FMT_API auto detail::thousands_sep_impl(locale_ref)
|
||||
template FMT_API auto thousands_sep_impl(locale_ref)
|
||||
-> thousands_sep_result<char>;
|
||||
template FMT_API char detail::decimal_point_impl(locale_ref);
|
||||
template FMT_API auto decimal_point_impl(locale_ref) -> char;
|
||||
|
||||
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
||||
template FMT_API void buffer<char>::append(const char*, const char*);
|
||||
|
||||
// DEPRECATED!
|
||||
// There is no correspondent extern template in format.h because of
|
||||
// incompatibility between clang and gcc (#2377).
|
||||
template FMT_API void detail::vformat_to(
|
||||
detail::buffer<char>&, string_view,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
||||
|
||||
template FMT_API int detail::format_float(double, int, detail::float_specs,
|
||||
detail::buffer<char>&);
|
||||
template FMT_API int detail::format_float(long double, int, detail::float_specs,
|
||||
detail::buffer<char>&);
|
||||
template FMT_API void vformat_to(buffer<char>&, string_view,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>,
|
||||
locale_ref);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template FMT_API auto detail::thousands_sep_impl(locale_ref)
|
||||
template FMT_API auto thousands_sep_impl(locale_ref)
|
||||
-> thousands_sep_result<wchar_t>;
|
||||
template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
|
||||
template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
|
||||
|
||||
template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
|
||||
const wchar_t*);
|
||||
|
||||
template struct detail::basic_data<void>;
|
||||
template FMT_API void buffer<wchar_t>::append(const wchar_t*, const wchar_t*);
|
||||
|
||||
} // namespace detail
|
||||
FMT_END_NAMESPACE
|
||||
|
13
Externals/fmt/src/os.cc
vendored
13
Externals/fmt/src/os.cc
vendored
@ -51,10 +51,6 @@
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef fileno
|
||||
# undef fileno
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// Return type of read and write functions.
|
||||
@ -173,7 +169,7 @@ void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||
if (msg) {
|
||||
utf16_to_utf8 utf8_message;
|
||||
if (utf8_message.convert(msg) == ERROR_SUCCESS) {
|
||||
format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message);
|
||||
fmt::format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -206,11 +202,8 @@ void buffered_file::close() {
|
||||
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
|
||||
}
|
||||
|
||||
// A macro used to prevent expansion of fileno on broken versions of MinGW.
|
||||
#define FMT_ARGS
|
||||
|
||||
int buffered_file::fileno() const {
|
||||
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
|
||||
int buffered_file::descriptor() const {
|
||||
int fd = FMT_POSIX_CALL(fileno(file_));
|
||||
if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
|
||||
return fd;
|
||||
}
|
||||
|
43
Externals/fmt/support/appveyor-build.py
vendored
43
Externals/fmt/support/appveyor-build.py
vendored
@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Build the project on AppVeyor.
|
||||
|
||||
import os
|
||||
from subprocess import check_call
|
||||
|
||||
build = os.environ['BUILD']
|
||||
config = os.environ['CONFIGURATION']
|
||||
platform = os.environ['PLATFORM']
|
||||
path = os.environ['PATH']
|
||||
image = os.environ['APPVEYOR_BUILD_WORKER_IMAGE']
|
||||
jobid = os.environ['APPVEYOR_JOB_ID']
|
||||
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config, '..']
|
||||
if build == 'mingw':
|
||||
cmake_command.append('-GMinGW Makefiles')
|
||||
build_command = ['mingw32-make', '-j4']
|
||||
test_command = ['mingw32-make', 'test']
|
||||
# Remove the path to Git bin directory from $PATH because it breaks
|
||||
# MinGW config.
|
||||
path = path.replace(r'C:\Program Files (x86)\Git\bin', '')
|
||||
os.environ['PATH'] = r'C:\MinGW\bin;' + path
|
||||
else:
|
||||
# Add MSBuild 14.0 to PATH as described in
|
||||
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
|
||||
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\15.0\Bin;' + path
|
||||
if image == 'Visual Studio 2019':
|
||||
generator = 'Visual Studio 16 2019'
|
||||
if platform == 'x64':
|
||||
cmake_command.extend(['-A', 'x64'])
|
||||
else:
|
||||
if image == 'Visual Studio 2015':
|
||||
generator = 'Visual Studio 14 2015'
|
||||
elif image == 'Visual Studio 2017':
|
||||
generator = 'Visual Studio 15 2017'
|
||||
if platform == 'x64':
|
||||
generator += ' Win64'
|
||||
cmake_command.append('-G' + generator)
|
||||
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
|
||||
test_command = ['ctest', '-C', config]
|
||||
|
||||
check_call(cmake_command)
|
||||
check_call(build_command)
|
||||
check_call(test_command)
|
31
Externals/fmt/support/appveyor.yml
vendored
31
Externals/fmt/support/appveyor.yml
vendored
@ -1,31 +0,0 @@
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
clone_depth: 1
|
||||
|
||||
image:
|
||||
- Visual Studio 2015
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
environment:
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
MSVC_DEFAULT_OPTIONS: ON
|
||||
BUILD: msvc
|
||||
|
||||
before_build:
|
||||
- mkdir build
|
||||
- cd build
|
||||
|
||||
build_script:
|
||||
- python ../support/appveyor-build.py
|
||||
|
||||
on_failure:
|
||||
- appveyor PushArtifact Testing/Temporary/LastTest.log
|
||||
- appveyor AddTest test
|
||||
|
||||
# Uncomment this to debug AppVeyor failures.
|
||||
#on_finish:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
2
Externals/fmt/support/bazel/.bazelversion
vendored
2
Externals/fmt/support/bazel/.bazelversion
vendored
@ -1 +1 @@
|
||||
5.0.0
|
||||
5.1.1
|
||||
|
7
Externals/fmt/support/bazel/BUILD.bazel
vendored
7
Externals/fmt/support/bazel/BUILD.bazel
vendored
@ -11,18 +11,17 @@ cc_library(
|
||||
"include/fmt/color.h",
|
||||
"include/fmt/compile.h",
|
||||
"include/fmt/core.h",
|
||||
"include/fmt/format.h",
|
||||
"include/fmt/format-inl.h",
|
||||
"include/fmt/locale.h",
|
||||
"include/fmt/format.h",
|
||||
"include/fmt/os.h",
|
||||
"include/fmt/ostream.h",
|
||||
"include/fmt/printf.h",
|
||||
"include/fmt/ranges.h",
|
||||
"include/fmt/std.h",
|
||||
"include/fmt/xchar.h",
|
||||
],
|
||||
includes = [
|
||||
"include",
|
||||
"src",
|
||||
"include",
|
||||
],
|
||||
strip_include_prefix = "include",
|
||||
visibility = ["//visibility:public"],
|
||||
|
@ -1,4 +1,7 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake)
|
||||
if (NOT TARGET fmt::fmt)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake)
|
||||
endif ()
|
||||
|
||||
check_required_components(fmt)
|
||||
|
6
Externals/fmt/support/manage.py
vendored
6
Externals/fmt/support/manage.py
vendored
@ -183,6 +183,12 @@ def update_site(env):
|
||||
with rewrite(index) as b:
|
||||
b.data = b.data.replace(
|
||||
'doc/latest/index.html#format-string-syntax', 'syntax.html')
|
||||
# Fix issues in syntax.rst.
|
||||
index = os.path.join(target_doc_dir, 'syntax.rst')
|
||||
with rewrite(index) as b:
|
||||
b.data = b.data.replace(
|
||||
'..productionlist:: sf\n', '.. productionlist:: sf\n ')
|
||||
b.data = b.data.replace('Examples:\n', 'Examples::\n')
|
||||
# Build the docs.
|
||||
html_dir = os.path.join(env.build_dir, 'html')
|
||||
if os.path.exists(html_dir):
|
||||
|
@ -132,7 +132,7 @@ std::string DSPDisassembler::DisassembleParameters(const DSPOPCTemplate& opc, u1
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR_LOG_FMT(DSPLLE, "Unknown parameter type: {:x}", opc.params[j].type);
|
||||
ERROR_LOG_FMT(DSPLLE, "Unknown parameter type: {:x}", static_cast<u32>(opc.params[j].type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -365,24 +365,39 @@ void DSPJitRegCache::FlushRegs()
|
||||
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register {} is still a simple reg", i);
|
||||
}
|
||||
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RSP].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", RSP);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RBX].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", RBX);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RBP].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RBP);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RSI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RSI);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RDI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RDI);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RSP].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}",
|
||||
static_cast<u32>(RSP));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RBX].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}",
|
||||
static_cast<u32>(RBX));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RBP].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(RBP));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RSI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(RSI));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[RDI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(RDI));
|
||||
#ifdef STATIC_REG_ACCS
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R8);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R9);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}",
|
||||
static_cast<u32>(R8));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}",
|
||||
static_cast<u32>(R9));
|
||||
#else
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R8);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R9);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R8));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R9));
|
||||
#endif
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R10].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R10);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R11].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R11);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R12].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R12);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R13].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R13);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R14].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R14);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R15);
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R10].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R10));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R11].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R11));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R12].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R12));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R13].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R13));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R14].guest_reg == DSP_REG_NONE, "wrong xreg state for {}",
|
||||
static_cast<u32>(R14));
|
||||
ASSERT_MSG(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}",
|
||||
static_cast<u32>(R15));
|
||||
|
||||
m_use_ctr = 0;
|
||||
}
|
||||
@ -968,15 +983,15 @@ void DSPJitRegCache::SpillXReg(X64Reg reg)
|
||||
if (m_xregs[reg].guest_reg <= DSP_REG_MAX_MEM_BACKED)
|
||||
{
|
||||
ASSERT_MSG(DSPLLE, !m_regs[m_xregs[reg].guest_reg].used,
|
||||
"to be spilled host reg {:#x} (guest reg {:#x}) still in use!", reg,
|
||||
m_xregs[reg].guest_reg);
|
||||
"to be spilled host reg {:#x} (guest reg {:#x}) still in use!",
|
||||
static_cast<u32>(reg), m_xregs[reg].guest_reg);
|
||||
|
||||
MovToMemory(m_xregs[reg].guest_reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MSG(DSPLLE, m_xregs[reg].guest_reg == DSP_REG_NONE,
|
||||
"to be spilled host reg {:#x} still in use!", reg);
|
||||
"to be spilled host reg {:#x} still in use!", static_cast<u32>(reg));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1021,7 +1036,7 @@ void DSPJitRegCache::GetXReg(X64Reg reg)
|
||||
{
|
||||
if (m_xregs[reg].guest_reg == DSP_REG_STATIC)
|
||||
{
|
||||
ERROR_LOG_FMT(DSPLLE, "Trying to get statically used XReg {}", reg);
|
||||
ERROR_LOG_FMT(DSPLLE, "Trying to get statically used XReg {}", static_cast<u32>(reg));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1037,7 +1052,7 @@ void DSPJitRegCache::PutXReg(X64Reg reg)
|
||||
{
|
||||
if (m_xregs[reg].guest_reg == DSP_REG_STATIC)
|
||||
{
|
||||
ERROR_LOG_FMT(DSPLLE, "Trying to put statically used XReg {}", reg);
|
||||
ERROR_LOG_FMT(DSPLLE, "Trying to put statically used XReg {}", static_cast<u32>(reg));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -14,15 +14,12 @@
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
|
||||
enum
|
||||
{
|
||||
FILE_ID = 0x0d01f1f0,
|
||||
VERSION_NUMBER = 5,
|
||||
MIN_LOADER_VERSION = 1,
|
||||
// This value is only used if the DFF file was created with overridden RAM sizes.
|
||||
// If the MIN_LOADER_VERSION ever exceeds this, it's alright to remove it.
|
||||
MIN_LOADER_VERSION_FOR_RAM_OVERRIDE = 5,
|
||||
};
|
||||
constexpr u32 FILE_ID = 0x0d01f1f0;
|
||||
constexpr u32 VERSION_NUMBER = 5;
|
||||
constexpr u32 MIN_LOADER_VERSION = 1;
|
||||
// This value is only used if the DFF file was created with overridden RAM sizes.
|
||||
// If the MIN_LOADER_VERSION ever exceeds this, it's alright to remove it.
|
||||
constexpr u32 MIN_LOADER_VERSION_FOR_RAM_OVERRIDE = 5;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
@ -210,7 +210,7 @@ void Wiimote::HandleExtensionSwap(ExtensionNumber desired_extension_number,
|
||||
else
|
||||
{
|
||||
INFO_LOG_FMT(WIIMOTE, "Switching to Extension {} (Wiimote {} in slot {})",
|
||||
desired_extension_number, m_index, m_bt_device_index);
|
||||
static_cast<u8>(desired_extension_number), m_index, m_bt_device_index);
|
||||
|
||||
m_active_extension = desired_extension_number;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ ESDevice::ESDevice(Kernel& ios, const std::string& device_name) : Device(ios, de
|
||||
if (result != FS::ResultCode::Success && result != FS::ResultCode::AlreadyExists)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "Failed to create {}: error {}", directory.path,
|
||||
FS::ConvertResult(result));
|
||||
static_cast<s32>(FS::ConvertResult(result)));
|
||||
}
|
||||
|
||||
// Now update the UID/GID and other attributes.
|
||||
@ -1060,7 +1060,8 @@ ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||
ret = iosc.ImportCertificate(ca_cert, IOSC::HANDLE_ROOT_KEY, ca_handle, PID_ES);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: IOSC_ImportCertificate(ca) failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: IOSC_ImportCertificate(ca) failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1075,7 +1076,7 @@ ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: IOSC_ImportCertificate(issuer) failed with error {}",
|
||||
ret);
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1084,7 +1085,8 @@ ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||
ret = iosc.VerifyPublicKeySign(signed_blob.GetSha1(), issuer_handle, signature, PID_ES);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: IOSC_VerifyPublicKeySign failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: IOSC_VerifyPublicKeySign failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1094,12 +1096,13 @@ ReturnCode ESDevice::VerifyContainer(VerifyContainerType type, VerifyMode mode,
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: Writing the issuer cert failed with return code {}",
|
||||
ret);
|
||||
static_cast<s32>(ret));
|
||||
}
|
||||
|
||||
ret = WriteNewCertToStore(ca_cert);
|
||||
if (ret != IPC_SUCCESS)
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: Writing the CA cert failed with return code {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifyContainer: Writing the CA cert failed with return code {}",
|
||||
static_cast<s32>(ret));
|
||||
}
|
||||
|
||||
if (ret == IPC_SUCCESS && issuer_handle_out)
|
||||
|
@ -146,14 +146,16 @@ ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u
|
||||
certs_bytes, ng_cert);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: VerifyContainer(ng) failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: VerifyContainer(ng) failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iosc.VerifyPublicKeySign(ap.GetSha1(), ng_cert, ap.GetSignatureData(), PID_ES);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_VerifyPublicKeySign(ap) failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_VerifyPublicKeySign(ap) failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -166,7 +168,8 @@ ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u
|
||||
ret = iosc.ImportPublicKey(ap_cert, ap.GetPublicKey().data(), nullptr, PID_ES);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_ImportPublicKey(ap) failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_ImportPublicKey(ap) failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -174,7 +177,8 @@ ReturnCode ESDevice::VerifySign(const std::vector<u8>& hash, const std::vector<u
|
||||
ret = iosc.VerifyPublicKeySign(hash_digest, ap_cert, ecc_signature, PID_ES);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_VerifyPublicKeySign(data) failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "VerifySign: IOSC_VerifyPublicKeySign(data) failed with error {}",
|
||||
static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ ReturnCode ESDevice::ImportTicket(const std::vector<u8>& ticket_bytes,
|
||||
if (ret < 0)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "ImportTicket: Failed to unpersonalise ticket for {:016x} ({})",
|
||||
ticket.GetTitleId(), ret);
|
||||
ticket.GetTitleId(), static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -156,7 +156,7 @@ ReturnCode ESDevice::ImportTmd(Context& context, const std::vector<u8>& tmd_byte
|
||||
context.title_import_export.tmd, cert_store);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "ImportTmd: VerifyContainer failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "ImportTmd: VerifyContainer failed with error {}", static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ ReturnCode ESDevice::ImportTmd(Context& context, const std::vector<u8>& tmd_byte
|
||||
&context.title_import_export.key_handle);
|
||||
if (ret != IPC_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_ES, "ImportTmd: InitBackupKey failed with error {}", ret);
|
||||
ERROR_LOG_FMT(IOS_ES, "ImportTmd: InitBackupKey failed with error {}", static_cast<s32>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ static void LogResult(ResultCode code, fmt::format_string<Args...> format, Args&
|
||||
code == ResultCode::Success ? Common::Log::LogLevel::LINFO : Common::Log::LogLevel::LERROR;
|
||||
|
||||
GENERIC_LOG_FMT(Common::Log::LogType::IOS_FS, type, "Command: {}: Result {}", command,
|
||||
ConvertResult(code));
|
||||
static_cast<s32>(ConvertResult(code)));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
|
@ -616,7 +616,8 @@ std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device
|
||||
std::optional<IPCReply> Kernel::OpenDevice(OpenRequest& request)
|
||||
{
|
||||
const s32 new_fd = GetFreeDeviceID();
|
||||
INFO_LOG_FMT(IOS, "Opening {} (mode {}, fd {})", request.path, request.flags, new_fd);
|
||||
INFO_LOG_FMT(IOS, "Opening {} (mode {}, fd {})", request.path, static_cast<u32>(request.flags),
|
||||
new_fd);
|
||||
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS, "Couldn't get a free fd, too many open files");
|
||||
@ -694,7 +695,7 @@ std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
|
||||
ret = device->IOCtlV(IOCtlVRequest{request.address});
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(IOS, false, "Unexpected command: {:#x}", request.command);
|
||||
ASSERT_MSG(IOS, false, "Unexpected command: {:#x}", static_cast<u32>(request.command));
|
||||
ret = IPCReply{IPC_EINVAL, 978_tbticks};
|
||||
break;
|
||||
}
|
||||
|
@ -210,7 +210,8 @@ static ErrorCode WriteFile(const std::string& filename, const std::vector<u8>& t
|
||||
f_write(&dst, tmp_buffer.data() + offset, chunk_size, &written_size);
|
||||
if (write_error_code != FR_OK)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_WC24, "Failed to write file {} to VFF {}", filename, write_error_code);
|
||||
ERROR_LOG_FMT(IOS_WC24, "Failed to write file {} to VFF: {}", filename,
|
||||
static_cast<u32>(write_error_code));
|
||||
return WC24_ERR_FILE_WRITE;
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ public:
|
||||
if (socket_entry == WiiSockets.end())
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_NET, "DoSock: Error, fd not found ({:08x}, {:08X}, {:08X})", sock,
|
||||
request.address, type);
|
||||
request.address, static_cast<u32>(type));
|
||||
GetIOS()->EnqueueIPCReply(request, -SO_EBADF);
|
||||
}
|
||||
else
|
||||
|
@ -666,7 +666,8 @@ void BluetoothRealDevice::HandleCtrlTransfer(libusb_transfer* tr)
|
||||
|
||||
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_WIIMOTE, "libusb command transfer failed, status: {:#04x}", tr->status);
|
||||
ERROR_LOG_FMT(IOS_WIIMOTE, "libusb command transfer failed, status: {:#04x}",
|
||||
static_cast<u32>(tr->status));
|
||||
if (!m_showed_failed_transfer.IsSet())
|
||||
{
|
||||
Core::DisplayMessage("Failed to send a command to the Bluetooth adapter.", 10000);
|
||||
@ -693,7 +694,8 @@ void BluetoothRealDevice::HandleBulkOrIntrTransfer(libusb_transfer* tr)
|
||||
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_TIMED_OUT &&
|
||||
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
||||
{
|
||||
ERROR_LOG_FMT(IOS_WIIMOTE, "libusb transfer failed, status: {:#04x}", tr->status);
|
||||
ERROR_LOG_FMT(IOS_WIIMOTE, "libusb transfer failed, status: {:#04x}",
|
||||
static_cast<u32>(tr->status));
|
||||
if (!m_showed_failed_transfer.IsSet())
|
||||
{
|
||||
Core::DisplayMessage("Failed to transfer to or from to the Bluetooth adapter.", 10000);
|
||||
|
@ -138,7 +138,7 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
|
||||
m_continue_install = Memory::Read_U32(request.buffer_in + 36);
|
||||
|
||||
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_INIT: patch type {}, continue install: {}",
|
||||
m_patch_type, m_continue_install ? "true" : "false");
|
||||
static_cast<u32>(m_patch_type), m_continue_install ? "true" : "false");
|
||||
|
||||
if (m_patch_type == PatchType::PATCH_TYPE_2)
|
||||
{
|
||||
|
@ -389,7 +389,7 @@ void RegCache::Discard(BitSet32 pregs)
|
||||
for (preg_t i : pregs)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg {} (X64 reg {}).",
|
||||
i, RX(i));
|
||||
i, static_cast<u32>(RX(i)));
|
||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress for {}!",
|
||||
i);
|
||||
|
||||
@ -413,7 +413,7 @@ void RegCache::Flush(BitSet32 pregs)
|
||||
for (preg_t i : pregs)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg {} (X64 reg {}).",
|
||||
i, RX(i));
|
||||
i, static_cast<u32>(RX(i)));
|
||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress for {}!",
|
||||
i);
|
||||
|
||||
@ -497,7 +497,7 @@ BitSet32 RegCache::RegistersInUse() const
|
||||
|
||||
void RegCache::FlushX(X64Reg reg)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, reg < m_xregs.size(), "Flushing non-existent reg {}", reg);
|
||||
ASSERT_MSG(DYNA_REC, reg < m_xregs.size(), "Flushing non-existent reg {}", static_cast<u32>(reg));
|
||||
ASSERT(!m_xregs[reg].IsLocked());
|
||||
if (!m_xregs[reg].IsFree())
|
||||
{
|
||||
@ -521,7 +521,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||
{
|
||||
X64Reg xr = GetFreeXReg();
|
||||
|
||||
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg {} already dirty", xr);
|
||||
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg {} already dirty", static_cast<u32>(xr));
|
||||
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register");
|
||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Invalid transaction state");
|
||||
|
||||
@ -538,7 +538,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||
[xr](const auto& r) {
|
||||
return r.Location().has_value() && r.Location()->IsSimpleReg(xr);
|
||||
}),
|
||||
"Xreg {} already bound", xr);
|
||||
"Xreg {} already bound", static_cast<u32>(xr));
|
||||
|
||||
m_regs[i].SetBoundTo(xr);
|
||||
}
|
||||
@ -551,7 +551,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, !m_xregs[RX(i)].IsLocked(),
|
||||
"WTF, this reg ({} -> {}) should have been flushed", i, RX(i));
|
||||
"WTF, this reg ({} -> {}) should have been flushed", i, static_cast<u32>(RX(i)));
|
||||
}
|
||||
|
||||
void RegCache::StoreFromRegister(preg_t i, FlushMode mode)
|
||||
|
@ -369,7 +369,8 @@ const u8* CommonAsmRoutines::GenQuantizedStoreRuntime(bool single, EQuantizeType
|
||||
const u8* load = AlignCode4();
|
||||
GenQuantizedStore(single, type, -1);
|
||||
RET();
|
||||
JitRegister::Register(start, GetCodePtr(), "JIT_QuantizedStore_{}_{}", type, single);
|
||||
JitRegister::Register(start, GetCodePtr(), "JIT_QuantizedStore_{}_{}", static_cast<u32>(type),
|
||||
single);
|
||||
|
||||
return load;
|
||||
}
|
||||
@ -400,7 +401,8 @@ const u8* CommonAsmRoutines::GenQuantizedLoadRuntime(bool single, EQuantizeType
|
||||
const u8* load = AlignCode4();
|
||||
GenQuantizedLoad(single, type, -1);
|
||||
RET();
|
||||
JitRegister::Register(start, GetCodePtr(), "JIT_QuantizedLoad_{}_{}", type, single);
|
||||
JitRegister::Register(start, GetCodePtr(), "JIT_QuantizedLoad_{}_{}", static_cast<u32>(type),
|
||||
single);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ static bool ImportWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad,
|
||||
if (ret != IOS::HLE::IOSC_FAIL_CHECKVALUE)
|
||||
{
|
||||
PanicAlertFmtT("WAD installation failed: Could not initialise title import (error {0}).",
|
||||
ret);
|
||||
static_cast<u32>(ret));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -548,7 +548,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||
const auto es = m_ios.GetES();
|
||||
if ((ret = es->ImportTicket(ticket.first, ticket.second)) < 0)
|
||||
{
|
||||
ERROR_LOG_FMT(CORE, "Failed to import ticket: error {}", ret);
|
||||
ERROR_LOG_FMT(CORE, "Failed to import ticket: error {}", static_cast<u32>(ret));
|
||||
return UpdateResult::ImportFailed;
|
||||
}
|
||||
|
||||
@ -580,7 +580,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||
IOS::HLE::ESDevice::Context context;
|
||||
if ((ret = es->ImportTitleInit(context, tmd.first.GetBytes(), tmd.second)) < 0)
|
||||
{
|
||||
ERROR_LOG_FMT(CORE, "Failed to initialise title import: error {}", ret);
|
||||
ERROR_LOG_FMT(CORE, "Failed to initialise title import: error {}", static_cast<u32>(ret));
|
||||
return UpdateResult::ImportFailed;
|
||||
}
|
||||
|
||||
@ -601,7 +601,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||
if ((ret = es->ImportContentBegin(context, title.id, content.id)) < 0)
|
||||
{
|
||||
ERROR_LOG_FMT(CORE, "Failed to initialise import for content {:08x}: error {}", content.id,
|
||||
ret);
|
||||
static_cast<u32>(ret));
|
||||
return UpdateResult::ImportFailed;
|
||||
}
|
||||
|
||||
@ -626,7 +626,7 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
|
||||
if ((all_contents_imported && (ret = es->ImportTitleDone(context)) < 0) ||
|
||||
(!all_contents_imported && (ret = es->ImportTitleCancel(context)) < 0))
|
||||
{
|
||||
ERROR_LOG_FMT(CORE, "Failed to finalise title import: error {}", ret);
|
||||
ERROR_LOG_FMT(CORE, "Failed to finalise title import: error {}", static_cast<u32>(ret));
|
||||
return UpdateResult::ImportFailed;
|
||||
}
|
||||
|
||||
|
@ -103,69 +103,18 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
: NativeVertexFormat(vtx_decl)
|
||||
|
||||
{
|
||||
const AttributeFormat* format = &vtx_decl.position;
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = SHADER_POSITION_ATTRIB;
|
||||
m_elems[m_num_elems].AlignedByteOffset = format->offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format->type, format->components, format->integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
AddAttribute(vtx_decl.position, ShaderAttrib::Position);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
format = &vtx_decl.normals[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = SHADER_NORMAL_ATTRIB + i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = format->offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format->type, format->components, format->integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
AddAttribute(vtx_decl.normals[i], ShaderAttrib::Normal + i);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
format = &vtx_decl.colors[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = SHADER_COLOR0_ATTRIB + i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = format->offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format->type, format->components, format->integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
AddAttribute(vtx_decl.colors[i], ShaderAttrib::Color0 + i);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
format = &vtx_decl.texcoords[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = SHADER_TEXTURE0_ATTRIB + i;
|
||||
m_elems[m_num_elems].AlignedByteOffset = format->offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format->type, format->components, format->integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
AddAttribute(vtx_decl.texcoords[i], ShaderAttrib::TexCoord0 + i);
|
||||
|
||||
format = &vtx_decl.posmtx;
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = SHADER_POSMTX_ATTRIB;
|
||||
m_elems[m_num_elems].AlignedByteOffset = format->offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format->type, format->components, format->integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
AddAttribute(vtx_decl.posmtx, ShaderAttrib::PositionMatrix);
|
||||
}
|
||||
|
||||
D3DVertexFormat::~D3DVertexFormat()
|
||||
@ -201,4 +150,17 @@ ID3D11InputLayout* D3DVertexFormat::GetInputLayout(const void* vs_bytecode, size
|
||||
return layout;
|
||||
}
|
||||
|
||||
void D3DVertexFormat::AddAttribute(const AttributeFormat& format, ShaderAttrib semantic_index)
|
||||
{
|
||||
if (format.enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
m_elems[m_num_elems].SemanticIndex = static_cast<u32>(semantic_index);
|
||||
m_elems[m_num_elems].AlignedByteOffset = format.offset;
|
||||
m_elems[m_num_elems].Format = VarToD3D(format.type, format.components, format.integer);
|
||||
m_elems[m_num_elems].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
++m_num_elems;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
#include "VideoCommon/VertexManagerBase.h"
|
||||
|
||||
enum class ShaderAttrib : u32;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
@ -22,6 +24,8 @@ public:
|
||||
ID3D11InputLayout* GetInputLayout(const void* vs_bytecode, size_t vs_bytecode_size);
|
||||
|
||||
private:
|
||||
void AddAttribute(const AttributeFormat& format, ShaderAttrib semantic_index);
|
||||
|
||||
std::array<D3D11_INPUT_ELEMENT_DESC, 32> m_elems{};
|
||||
UINT m_num_elems = 0;
|
||||
|
||||
|
@ -59,14 +59,14 @@ void DXVertexFormat::GetInputLayoutDesc(D3D12_INPUT_LAYOUT_DESC* desc) const
|
||||
desc->NumElements = m_num_attributes;
|
||||
}
|
||||
|
||||
void DXVertexFormat::AddAttribute(const char* semantic_name, u32 semantic_index, u32 slot,
|
||||
void DXVertexFormat::AddAttribute(const char* semantic_name, ShaderAttrib semantic_index, u32 slot,
|
||||
DXGI_FORMAT format, u32 offset)
|
||||
{
|
||||
ASSERT(m_num_attributes < MAX_VERTEX_ATTRIBUTES);
|
||||
|
||||
auto* attr_desc = &m_attribute_descriptions[m_num_attributes];
|
||||
attr_desc->SemanticName = semantic_name;
|
||||
attr_desc->SemanticIndex = semantic_index;
|
||||
attr_desc->SemanticIndex = static_cast<u32>(semantic_index);
|
||||
attr_desc->Format = format;
|
||||
attr_desc->InputSlot = slot;
|
||||
attr_desc->AlignedByteOffset = offset;
|
||||
@ -83,38 +83,38 @@ void DXVertexFormat::MapAttributes()
|
||||
if (m_decl.position.enable)
|
||||
{
|
||||
AddAttribute(
|
||||
"TEXCOORD", SHADER_POSITION_ATTRIB, 0,
|
||||
"TEXCOORD", ShaderAttrib::Position, 0,
|
||||
VarToDXGIFormat(m_decl.position.type, m_decl.position.components, m_decl.position.integer),
|
||||
m_decl.position.offset);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
if (m_decl.normals[i].enable)
|
||||
{
|
||||
AddAttribute("TEXCOORD", SHADER_NORMAL_ATTRIB + i, 0,
|
||||
AddAttribute("TEXCOORD", ShaderAttrib::Normal + i, 0,
|
||||
VarToDXGIFormat(m_decl.normals[i].type, m_decl.normals[i].components,
|
||||
m_decl.normals[i].integer),
|
||||
m_decl.normals[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_decl.colors[i].enable)
|
||||
{
|
||||
AddAttribute("TEXCOORD", SHADER_COLOR0_ATTRIB + i, 0,
|
||||
AddAttribute("TEXCOORD", ShaderAttrib::Color0 + i, 0,
|
||||
VarToDXGIFormat(m_decl.colors[i].type, m_decl.colors[i].components,
|
||||
m_decl.colors[i].integer),
|
||||
m_decl.colors[i].offset);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 8; i++)
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if (m_decl.texcoords[i].enable)
|
||||
{
|
||||
AddAttribute("TEXCOORD", SHADER_TEXTURE0_ATTRIB + i, 0,
|
||||
AddAttribute("TEXCOORD", ShaderAttrib::TexCoord0 + i, 0,
|
||||
VarToDXGIFormat(m_decl.texcoords[i].type, m_decl.texcoords[i].components,
|
||||
m_decl.texcoords[i].integer),
|
||||
m_decl.texcoords[i].offset);
|
||||
@ -124,7 +124,7 @@ void DXVertexFormat::MapAttributes()
|
||||
if (m_decl.posmtx.enable)
|
||||
{
|
||||
AddAttribute(
|
||||
"TEXCOORD", SHADER_POSMTX_ATTRIB, 0,
|
||||
"TEXCOORD", ShaderAttrib::PositionMatrix, 0,
|
||||
VarToDXGIFormat(m_decl.posmtx.type, m_decl.posmtx.components, m_decl.posmtx.integer),
|
||||
m_decl.posmtx.offset);
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
|
||||
enum class ShaderAttrib : u32;
|
||||
|
||||
namespace DX12
|
||||
{
|
||||
class DXVertexFormat : public NativeVertexFormat
|
||||
@ -22,8 +24,8 @@ public:
|
||||
void GetInputLayoutDesc(D3D12_INPUT_LAYOUT_DESC* desc) const;
|
||||
|
||||
private:
|
||||
void AddAttribute(const char* semantic_name, u32 semantic_index, u32 slot, DXGI_FORMAT format,
|
||||
u32 offset);
|
||||
void AddAttribute(const char* semantic_name, ShaderAttrib semantic_index, u32 slot,
|
||||
DXGI_FORMAT format, u32 offset);
|
||||
void MapAttributes();
|
||||
|
||||
std::array<D3D12_INPUT_ELEMENT_DESC, MAX_VERTEX_ATTRIBUTES> m_attribute_descriptions = {};
|
||||
|
@ -113,18 +113,20 @@ static MTLVertexFormat ConvertFormat(ComponentFormat format, int count, bool int
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
static void SetAttribute(MTLVertexDescriptor* desc, u32 attribute, const AttributeFormat& format)
|
||||
static void SetAttribute(MTLVertexDescriptor* desc, ShaderAttrib attribute,
|
||||
const AttributeFormat& format)
|
||||
{
|
||||
if (!format.enable)
|
||||
return;
|
||||
MTLVertexAttributeDescriptor* attr_desc = [[desc attributes] objectAtIndexedSubscript:attribute];
|
||||
MTLVertexAttributeDescriptor* attr_desc =
|
||||
[[desc attributes] objectAtIndexedSubscript:(u32)attribute];
|
||||
[attr_desc setFormat:ConvertFormat(format.type, format.components, format.integer)];
|
||||
[attr_desc setOffset:format.offset];
|
||||
[attr_desc setBufferIndex:0];
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static void SetAttributes(MTLVertexDescriptor* desc, u32 attribute,
|
||||
static void SetAttributes(MTLVertexDescriptor* desc, ShaderAttrib attribute,
|
||||
const std::array<AttributeFormat, N>& format)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
@ -135,9 +137,9 @@ Metal::VertexFormat::VertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
: NativeVertexFormat(vtx_decl), m_desc(MRCTransfer([MTLVertexDescriptor new]))
|
||||
{
|
||||
[[[m_desc layouts] objectAtIndexedSubscript:0] setStride:vtx_decl.stride];
|
||||
SetAttribute(m_desc, SHADER_POSITION_ATTRIB, vtx_decl.position);
|
||||
SetAttributes(m_desc, SHADER_NORMAL_ATTRIB, vtx_decl.normals);
|
||||
SetAttributes(m_desc, SHADER_COLOR0_ATTRIB, vtx_decl.colors);
|
||||
SetAttributes(m_desc, SHADER_TEXTURE0_ATTRIB, vtx_decl.texcoords);
|
||||
SetAttribute(m_desc, SHADER_POSMTX_ATTRIB, vtx_decl.posmtx);
|
||||
SetAttribute(m_desc, ShaderAttrib::Position, vtx_decl.position);
|
||||
SetAttributes(m_desc, ShaderAttrib::Normal, vtx_decl.normals);
|
||||
SetAttributes(m_desc, ShaderAttrib::Color0, vtx_decl.colors);
|
||||
SetAttributes(m_desc, ShaderAttrib::TexCoord0, vtx_decl.texcoords);
|
||||
SetAttribute(m_desc, ShaderAttrib::PositionMatrix, vtx_decl.posmtx);
|
||||
}
|
||||
|
@ -32,18 +32,18 @@ static inline GLuint VarToGL(ComponentFormat t)
|
||||
return lookup[t];
|
||||
}
|
||||
|
||||
static void SetPointer(u32 attrib, u32 stride, const AttributeFormat& format)
|
||||
static void SetPointer(ShaderAttrib attrib, u32 stride, const AttributeFormat& format)
|
||||
{
|
||||
if (!format.enable)
|
||||
return;
|
||||
|
||||
glEnableVertexAttribArray(attrib);
|
||||
glEnableVertexAttribArray(static_cast<GLuint>(attrib));
|
||||
if (format.integer)
|
||||
glVertexAttribIPointer(attrib, format.components, VarToGL(format.type), stride,
|
||||
(u8*)nullptr + format.offset);
|
||||
glVertexAttribIPointer(static_cast<GLuint>(attrib), format.components, VarToGL(format.type),
|
||||
stride, (u8*)nullptr + format.offset);
|
||||
else
|
||||
glVertexAttribPointer(attrib, format.components, VarToGL(format.type), true, stride,
|
||||
(u8*)nullptr + format.offset);
|
||||
glVertexAttribPointer(static_cast<GLuint>(attrib), format.components, VarToGL(format.type),
|
||||
true, stride, (u8*)nullptr + format.offset);
|
||||
}
|
||||
|
||||
GLVertexFormat::GLVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
@ -65,18 +65,18 @@ GLVertexFormat::GLVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vm->GetIndexBufferHandle());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vm->GetVertexBufferHandle());
|
||||
|
||||
SetPointer(SHADER_POSITION_ATTRIB, vertex_stride, vtx_decl.position);
|
||||
SetPointer(ShaderAttrib::Position, vertex_stride, vtx_decl.position);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
SetPointer(SHADER_NORMAL_ATTRIB + i, vertex_stride, vtx_decl.normals[i]);
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
SetPointer(ShaderAttrib::Normal + i, vertex_stride, vtx_decl.normals[i]);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
SetPointer(SHADER_COLOR0_ATTRIB + i, vertex_stride, vtx_decl.colors[i]);
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
SetPointer(ShaderAttrib::Color0 + i, vertex_stride, vtx_decl.colors[i]);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
SetPointer(SHADER_TEXTURE0_ATTRIB + i, vertex_stride, vtx_decl.texcoords[i]);
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
SetPointer(ShaderAttrib::TexCoord0 + i, vertex_stride, vtx_decl.texcoords[i]);
|
||||
|
||||
SetPointer(SHADER_POSMTX_ATTRIB, vertex_stride, vtx_decl.posmtx);
|
||||
SetPointer(ShaderAttrib::PositionMatrix, vertex_stride, vtx_decl.posmtx);
|
||||
}
|
||||
|
||||
GLVertexFormat::~GLVertexFormat()
|
||||
|
@ -133,23 +133,24 @@ void SHADER::SetProgramBindings(bool is_compute)
|
||||
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
|
||||
}
|
||||
// Need to set some attribute locations
|
||||
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Position), "rawpos");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "posmtx");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::PositionMatrix), "posmtx");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "rawcolor0");
|
||||
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "rawcolor1");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Color0), "rawcolor0");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Color1), "rawcolor1");
|
||||
|
||||
glBindAttribLocation(glprogid, SHADER_NORMAL_ATTRIB, "rawnormal");
|
||||
glBindAttribLocation(glprogid, SHADER_TANGENT_ATTRIB, "rawtangent");
|
||||
glBindAttribLocation(glprogid, SHADER_BINORMAL_ATTRIB, "rawbinormal");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Normal), "rawnormal");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Tangent), "rawtangent");
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::Binormal), "rawbinormal");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// Per documentation: OpenGL copies the name string when glBindAttribLocation is called, so an
|
||||
// application may free its copy of the name string immediately after the function returns.
|
||||
glBindAttribLocation(glprogid, SHADER_TEXTURE0_ATTRIB + i, fmt::format("rawtex{}", i).c_str());
|
||||
glBindAttribLocation(glprogid, static_cast<GLuint>(ShaderAttrib::TexCoord0 + i),
|
||||
fmt::format("rawtex{}", i).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,13 +310,15 @@ void Renderer::BindBackbuffer(const ClearColor& clear_color)
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG_FMT(VIDEO, "Unknown present error {:#010X}, please report.", res);
|
||||
ERROR_LOG_FMT(VIDEO, "Unknown present error {:#010X} {}, please report.",
|
||||
static_cast<u32>(res), VkResultToString(res));
|
||||
m_swap_chain->RecreateSwapChain();
|
||||
}
|
||||
|
||||
res = m_swap_chain->AcquireNextImage();
|
||||
if (res != VK_SUCCESS)
|
||||
PanicAlertFmt("Failed to grab image from swap chain: {:#010X}", res);
|
||||
PanicAlertFmt("Failed to grab image from swap chain: {:#010X} {}", static_cast<u32>(res),
|
||||
VkResultToString(res));
|
||||
}
|
||||
|
||||
// Transition from undefined (or present src, but it can be substituted) to
|
||||
|
@ -66,14 +66,14 @@ void VertexFormat::MapAttributes()
|
||||
|
||||
if (m_decl.position.enable)
|
||||
AddAttribute(
|
||||
SHADER_POSITION_ATTRIB, 0,
|
||||
ShaderAttrib::Position, 0,
|
||||
VarToVkFormat(m_decl.position.type, m_decl.position.components, m_decl.position.integer),
|
||||
m_decl.position.offset);
|
||||
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (m_decl.normals[i].enable)
|
||||
AddAttribute(SHADER_NORMAL_ATTRIB + i, 0,
|
||||
AddAttribute(ShaderAttrib::Normal + i, 0,
|
||||
VarToVkFormat(m_decl.normals[i].type, m_decl.normals[i].components,
|
||||
m_decl.normals[i].integer),
|
||||
m_decl.normals[i].offset);
|
||||
@ -82,7 +82,7 @@ void VertexFormat::MapAttributes()
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
if (m_decl.colors[i].enable)
|
||||
AddAttribute(SHADER_COLOR0_ATTRIB + i, 0,
|
||||
AddAttribute(ShaderAttrib::Color0 + i, 0,
|
||||
VarToVkFormat(m_decl.colors[i].type, m_decl.colors[i].components,
|
||||
m_decl.colors[i].integer),
|
||||
m_decl.colors[i].offset);
|
||||
@ -91,14 +91,14 @@ void VertexFormat::MapAttributes()
|
||||
for (uint32_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (m_decl.texcoords[i].enable)
|
||||
AddAttribute(SHADER_TEXTURE0_ATTRIB + i, 0,
|
||||
AddAttribute(ShaderAttrib::TexCoord0 + i, 0,
|
||||
VarToVkFormat(m_decl.texcoords[i].type, m_decl.texcoords[i].components,
|
||||
m_decl.texcoords[i].integer),
|
||||
m_decl.texcoords[i].offset);
|
||||
}
|
||||
|
||||
if (m_decl.posmtx.enable)
|
||||
AddAttribute(SHADER_POSMTX_ATTRIB, 0,
|
||||
AddAttribute(ShaderAttrib::PositionMatrix, 0,
|
||||
VarToVkFormat(m_decl.posmtx.type, m_decl.posmtx.components, m_decl.posmtx.integer),
|
||||
m_decl.posmtx.offset);
|
||||
}
|
||||
@ -118,12 +118,12 @@ void VertexFormat::SetupInputState()
|
||||
m_input_state_info.pVertexAttributeDescriptions = m_attribute_descriptions.data();
|
||||
}
|
||||
|
||||
void VertexFormat::AddAttribute(uint32_t location, uint32_t binding, VkFormat format,
|
||||
void VertexFormat::AddAttribute(ShaderAttrib location, uint32_t binding, VkFormat format,
|
||||
uint32_t offset)
|
||||
{
|
||||
ASSERT(m_num_attributes < MAX_VERTEX_ATTRIBUTES);
|
||||
|
||||
m_attribute_descriptions[m_num_attributes].location = location;
|
||||
m_attribute_descriptions[m_num_attributes].location = static_cast<uint32_t>(location);
|
||||
m_attribute_descriptions[m_num_attributes].binding = binding;
|
||||
m_attribute_descriptions[m_num_attributes].format = format;
|
||||
m_attribute_descriptions[m_num_attributes].offset = offset;
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "VideoBackends/Vulkan/Constants.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
|
||||
enum class ShaderAttrib : u32;
|
||||
|
||||
namespace Vulkan
|
||||
{
|
||||
class VertexFormat : public ::NativeVertexFormat
|
||||
@ -23,7 +25,7 @@ public:
|
||||
void SetupInputState();
|
||||
|
||||
private:
|
||||
void AddAttribute(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset);
|
||||
void AddAttribute(ShaderAttrib location, uint32_t binding, VkFormat format, uint32_t offset);
|
||||
|
||||
VkVertexInputBindingDescription m_binding_description = {};
|
||||
|
||||
|
@ -107,7 +107,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value)
|
||||
WARN_LOG_FMT(VIDEO,
|
||||
"CP MATINDEX_A: an exact value of {:02x} was expected "
|
||||
"but instead a value of {:02x} was seen",
|
||||
MATINDEX_A, sub_cmd);
|
||||
static_cast<u16>(MATINDEX_A), sub_cmd);
|
||||
}
|
||||
|
||||
matrix_index_a.Hex = value;
|
||||
@ -120,7 +120,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value)
|
||||
WARN_LOG_FMT(VIDEO,
|
||||
"CP MATINDEX_B: an exact value of {:02x} was expected "
|
||||
"but instead a value of {:02x} was seen",
|
||||
MATINDEX_B, sub_cmd);
|
||||
static_cast<u16>(MATINDEX_B), sub_cmd);
|
||||
}
|
||||
|
||||
matrix_index_b.Hex = value;
|
||||
@ -133,7 +133,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value)
|
||||
WARN_LOG_FMT(VIDEO,
|
||||
"CP VCD_LO: an exact value of {:02x} was expected "
|
||||
"but instead a value of {:02x} was seen",
|
||||
VCD_LO, sub_cmd);
|
||||
static_cast<u16>(VCD_LO), sub_cmd);
|
||||
}
|
||||
|
||||
vtx_desc.low.Hex = value;
|
||||
@ -146,7 +146,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value)
|
||||
WARN_LOG_FMT(VIDEO,
|
||||
"CP VCD_HI: an exact value of {:02x} was expected "
|
||||
"but instead a value of {:02x} was seen",
|
||||
VCD_HI, sub_cmd);
|
||||
static_cast<u16>(VCD_HI), sub_cmd);
|
||||
}
|
||||
|
||||
vtx_desc.high.Hex = value;
|
||||
|
@ -98,16 +98,16 @@ void EmitVertexMainDeclaration(ShaderCode& code, u32 num_tex_inputs, u32 num_col
|
||||
{
|
||||
for (u32 i = 0; i < num_tex_inputs; i++)
|
||||
{
|
||||
const auto attribute = SHADER_TEXTURE0_ATTRIB + i;
|
||||
code.Write("ATTRIBUTE_LOCATION({}) in float3 rawtex{};\n", attribute, i);
|
||||
const auto attribute = ShaderAttrib::TexCoord0 + i;
|
||||
code.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawtex{};\n", attribute, i);
|
||||
}
|
||||
for (u32 i = 0; i < num_color_inputs; i++)
|
||||
{
|
||||
const auto attribute = SHADER_COLOR0_ATTRIB + i;
|
||||
code.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor{};\n", attribute, i);
|
||||
const auto attribute = ShaderAttrib::Color0 + i;
|
||||
code.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawcolor{};\n", attribute, i);
|
||||
}
|
||||
if (position_input)
|
||||
code.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB);
|
||||
code.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawpos;\n", ShaderAttrib::Position);
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
|
||||
{
|
||||
|
@ -118,10 +118,12 @@ void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view wor
|
||||
|
||||
out.Write(" if ({} != 0u) {{\n", BitfieldExtract<&LitChannel::enablelighting>("alphareg"));
|
||||
out.Write(" if ({} != 0u) {{\n", BitfieldExtract<&LitChannel::ambsource>("alphareg"));
|
||||
out.Write(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
|
||||
out.Write(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n",
|
||||
static_cast<u32>(VB_HAS_COL0));
|
||||
out.Write(" lacc.w = int(round(((chan == 0u) ? {}.w : {}.w) * 255.0));\n", in_color_0_var,
|
||||
in_color_1_var);
|
||||
out.Write(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0);
|
||||
out.Write(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n",
|
||||
static_cast<u32>(VB_HAS_COL0));
|
||||
out.Write(" lacc.w = int(round({}.w * 255.0));\n", in_color_0_var);
|
||||
out.Write(" else\n"
|
||||
" lacc.w = 255;\n"
|
||||
|
@ -147,15 +147,15 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in uint4 posmtx;\n", SHADER_POSMTX_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnormal;\n", SHADER_NORMAL_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtangent;\n", SHADER_TANGENT_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawbinormal;\n", SHADER_BINORMAL_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor0;\n", SHADER_COLOR0_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor1;\n", SHADER_COLOR1_ATTRIB);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtex{};\n", SHADER_TEXTURE0_ATTRIB + i, i);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawpos;\n", ShaderAttrib::Position);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in uint4 posmtx;\n", ShaderAttrib::PositionMatrix);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawnormal;\n", ShaderAttrib::Normal);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawtangent;\n", ShaderAttrib::Tangent);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawbinormal;\n", ShaderAttrib::Binormal);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawcolor0;\n", ShaderAttrib::Color0);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawcolor1;\n", ShaderAttrib::Color1);
|
||||
for (u32 i = 0; i < 8; ++i)
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawtex{};\n", ShaderAttrib::TexCoord0 + i, i);
|
||||
}
|
||||
|
||||
if (host_config.backend_geometry_shaders)
|
||||
@ -223,7 +223,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
"float3 N2;\n"
|
||||
"\n"
|
||||
"if ((components & {}u) != 0u) {{ // VB_HAS_POSMTXIDX\n",
|
||||
VB_HAS_POSMTXIDX);
|
||||
static_cast<u32>(VB_HAS_POSMTXIDX));
|
||||
LoadVertexAttribute(out, host_config, 2, "posmtx", "uint4", "ubyte4");
|
||||
out.Write(" // Vertex format has a per-vertex matrix\n"
|
||||
" int posidx = int(posmtx.r);\n"
|
||||
@ -258,7 +258,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
"float3 _normal = float3(0.0, 0.0, 0.0);\n"
|
||||
"if ((components & {}u) != 0u) // VB_HAS_NORMAL\n"
|
||||
"{{\n",
|
||||
VB_HAS_NORMAL);
|
||||
static_cast<u32>(VB_HAS_NORMAL));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawnormal", "float3", "float3");
|
||||
out.Write(" _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, "
|
||||
"rawnormal)));\n"
|
||||
@ -267,7 +267,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
"float3 _tangent = float3(0.0, 0.0, 0.0);\n"
|
||||
"if ((components & {}u) != 0u) // VB_HAS_TANGENT\n"
|
||||
"{{\n",
|
||||
VB_HAS_TANGENT);
|
||||
static_cast<u32>(VB_HAS_TANGENT));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawtangent", "float3", "float3");
|
||||
out.Write(" _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, rawtangent));\n"
|
||||
"}}\n"
|
||||
@ -280,7 +280,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
"float3 _binormal = float3(0.0, 0.0, 0.0);\n"
|
||||
"if ((components & {}u) != 0u) // VB_HAS_BINORMAL\n"
|
||||
"{{\n",
|
||||
VB_HAS_BINORMAL);
|
||||
static_cast<u32>(VB_HAS_BINORMAL));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawbinormal", "float3", "float3");
|
||||
out.Write(" _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, "
|
||||
"rawbinormal));\n"
|
||||
@ -301,11 +301,11 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
out.Write("// To use color 1, the vertex descriptor must have color 0 and 1.\n"
|
||||
"// If color 1 is present but not color 0, it is used for lighting channel 0.\n"
|
||||
"bool use_color_1 = ((components & {0}u) == {0}u); // VB_HAS_COL0 | VB_HAS_COL1\n",
|
||||
VB_HAS_COL0 | VB_HAS_COL1);
|
||||
static_cast<u32>(VB_HAS_COL0 | VB_HAS_COL1));
|
||||
|
||||
out.Write("if ((components & {0}u) == {0}u) // VB_HAS_COL0 | VB_HAS_COL1\n"
|
||||
"{{\n",
|
||||
VB_HAS_COL0 | VB_HAS_COL1);
|
||||
static_cast<u32>(VB_HAS_COL0 | VB_HAS_COL1));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawcolor0", "float4", "ubyte4");
|
||||
LoadVertexAttribute(out, host_config, 2, "rawcolor1", "float4", "ubyte4");
|
||||
out.Write(" vertex_color_0 = rawcolor0;\n"
|
||||
@ -313,14 +313,14 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
"}}\n"
|
||||
"else if ((components & {}u) != 0u) // VB_HAS_COL0\n"
|
||||
"{{\n",
|
||||
VB_HAS_COL0);
|
||||
static_cast<u32>(VB_HAS_COL0));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawcolor0", "float4", "ubyte4");
|
||||
out.Write(" vertex_color_0 = rawcolor0;\n"
|
||||
" vertex_color_1 = rawcolor0;\n"
|
||||
"}}\n"
|
||||
"else if ((components & {}u) != 0u) // VB_HAS_COL1\n"
|
||||
"{{\n",
|
||||
VB_HAS_COL1);
|
||||
static_cast<u32>(VB_HAS_COL1));
|
||||
LoadVertexAttribute(out, host_config, 2, "rawcolor1", "float4", "ubyte4");
|
||||
out.Write(" vertex_color_0 = rawcolor1;\n"
|
||||
" vertex_color_1 = rawcolor1;\n"
|
||||
@ -355,7 +355,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
|
||||
" float4 other_p1 = P1;\n"
|
||||
" float4 other_p2 = P2;\n"
|
||||
" if ((components & {}u) != 0u) {{ // VB_HAS_POSMTXIDX\n",
|
||||
VB_HAS_POSMTXIDX);
|
||||
static_cast<u32>(VB_HAS_POSMTXIDX));
|
||||
out.Write(" uint other_posidx = load_input_uint4_ubyte4(other_base_offset, "
|
||||
"vertex_offset_posmtx).r;\n"
|
||||
" other_p0 = " I_TRANSFORMMATRICES "[other_posidx];\n"
|
||||
@ -545,7 +545,7 @@ static void GenVertexShaderTexGens(APIType api_type, const ShaderHostConfig& hos
|
||||
out.Write(" case {:s}:\n", SourceRow::Normal);
|
||||
out.Write(" if ((components & {}u) != 0u) // VB_HAS_NORMAL\n"
|
||||
" {{\n",
|
||||
VB_HAS_NORMAL);
|
||||
static_cast<u32>(VB_HAS_NORMAL));
|
||||
LoadVertexAttribute(out, host_config, 6, "rawnormal", "float3", "float3");
|
||||
out.Write(" coord.xyz = rawnormal.xyz;\n"
|
||||
" }}\n"
|
||||
@ -553,7 +553,7 @@ static void GenVertexShaderTexGens(APIType api_type, const ShaderHostConfig& hos
|
||||
out.Write(" case {:s}:\n", SourceRow::BinormalT);
|
||||
out.Write(" if ((components & {}u) != 0u) // VB_HAS_TANGENT\n"
|
||||
" {{\n",
|
||||
VB_HAS_TANGENT);
|
||||
static_cast<u32>(VB_HAS_TANGENT));
|
||||
LoadVertexAttribute(out, host_config, 6, "rawtangent", "float3", "float3");
|
||||
out.Write(" coord.xyz = rawtangent.xyz;\n"
|
||||
" }}\n"
|
||||
@ -561,7 +561,7 @@ static void GenVertexShaderTexGens(APIType api_type, const ShaderHostConfig& hos
|
||||
out.Write(" case {:s}:\n", SourceRow::BinormalB);
|
||||
out.Write(" if ((components & {}u) != 0u) // VB_HAS_BINORMAL\n"
|
||||
" {{\n",
|
||||
VB_HAS_BINORMAL);
|
||||
static_cast<u32>(VB_HAS_BINORMAL));
|
||||
LoadVertexAttribute(out, host_config, 6, "rawbinormal", "float3", "float3");
|
||||
out.Write(" coord.xyz = rawbinormal.xyz;\n"
|
||||
" }}\n"
|
||||
@ -625,7 +625,7 @@ static void GenVertexShaderTexGens(APIType api_type, const ShaderHostConfig& hos
|
||||
out.Write(" default:\n"
|
||||
" {{\n");
|
||||
out.Write(" if ((components & ({}u /* VB_HAS_TEXMTXIDX0 */ << texgen)) != 0u) {{\n",
|
||||
VB_HAS_TEXMTXIDX0);
|
||||
static_cast<u32>(VB_HAS_TEXMTXIDX0));
|
||||
if (host_config.backend_dynamic_vertex_loader || host_config.backend_vs_point_line_expand)
|
||||
{
|
||||
out.Write(" int tmp = int(load_input_float3_rawtex(vertex_base_offset, "
|
||||
|
@ -118,20 +118,20 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
|
||||
|
||||
if (uid_data->vs_expand == VSExpand::None)
|
||||
{
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawpos;\n", ShaderAttrib::Position);
|
||||
if ((uid_data->components & VB_HAS_POSMTXIDX) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in uint4 posmtx;\n", SHADER_POSMTX_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in uint4 posmtx;\n", ShaderAttrib::PositionMatrix);
|
||||
if ((uid_data->components & VB_HAS_NORMAL) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnormal;\n", SHADER_NORMAL_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawnormal;\n", ShaderAttrib::Normal);
|
||||
if ((uid_data->components & VB_HAS_TANGENT) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtangent;\n", SHADER_TANGENT_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawtangent;\n", ShaderAttrib::Tangent);
|
||||
if ((uid_data->components & VB_HAS_BINORMAL) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float3 rawbinormal;\n", SHADER_BINORMAL_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float3 rawbinormal;\n", ShaderAttrib::Binormal);
|
||||
|
||||
if ((uid_data->components & VB_HAS_COL0) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor0;\n", SHADER_COLOR0_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawcolor0;\n", ShaderAttrib::Color0);
|
||||
if ((uid_data->components & VB_HAS_COL1) != 0)
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor1;\n", SHADER_COLOR1_ATTRIB);
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float4 rawcolor1;\n", ShaderAttrib::Color1);
|
||||
|
||||
for (u32 i = 0; i < 8; ++i)
|
||||
{
|
||||
@ -139,7 +139,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
|
||||
|
||||
if ((uid_data->components & (VB_HAS_UV0 << i)) != 0 || has_texmtx != 0)
|
||||
{
|
||||
out.Write("ATTRIBUTE_LOCATION({}) in float{} rawtex{};\n", SHADER_TEXTURE0_ATTRIB + i,
|
||||
out.Write("ATTRIBUTE_LOCATION({:s}) in float{} rawtex{};\n", ShaderAttrib::TexCoord0 + i,
|
||||
has_texmtx != 0 ? 3 : 2, i);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumFormatter.h"
|
||||
|
||||
#include "VideoCommon/LightingShaderGen.h"
|
||||
#include "VideoCommon/ShaderGenCommon.h"
|
||||
|
||||
@ -14,25 +16,39 @@ enum class SourceRow : u32;
|
||||
enum class VSExpand : u32;
|
||||
|
||||
// TODO should be reordered
|
||||
enum : int
|
||||
enum class ShaderAttrib : u32
|
||||
{
|
||||
SHADER_POSITION_ATTRIB = 0,
|
||||
SHADER_POSMTX_ATTRIB = 1,
|
||||
SHADER_NORMAL_ATTRIB = 2,
|
||||
SHADER_TANGENT_ATTRIB = 3,
|
||||
SHADER_BINORMAL_ATTRIB = 4,
|
||||
SHADER_COLOR0_ATTRIB = 5,
|
||||
SHADER_COLOR1_ATTRIB = 6,
|
||||
Position = 0,
|
||||
PositionMatrix = 1,
|
||||
Normal = 2,
|
||||
Tangent = 3,
|
||||
Binormal = 4,
|
||||
Color0 = 5,
|
||||
Color1 = 6,
|
||||
|
||||
SHADER_TEXTURE0_ATTRIB = 8,
|
||||
SHADER_TEXTURE1_ATTRIB = 9,
|
||||
SHADER_TEXTURE2_ATTRIB = 10,
|
||||
SHADER_TEXTURE3_ATTRIB = 11,
|
||||
SHADER_TEXTURE4_ATTRIB = 12,
|
||||
SHADER_TEXTURE5_ATTRIB = 13,
|
||||
SHADER_TEXTURE6_ATTRIB = 14,
|
||||
SHADER_TEXTURE7_ATTRIB = 15
|
||||
TexCoord0 = 8,
|
||||
TexCoord1 = 9,
|
||||
TexCoord2 = 10,
|
||||
TexCoord3 = 11,
|
||||
TexCoord4 = 12,
|
||||
TexCoord5 = 13,
|
||||
TexCoord6 = 14,
|
||||
TexCoord7 = 15
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<ShaderAttrib> : EnumFormatter<ShaderAttrib::TexCoord7>
|
||||
{
|
||||
static constexpr array_type names = {
|
||||
"Position", "Position Matrix", "Normal", "Tangent", "Binormal", "Color 0",
|
||||
"Color 1", nullptr, "Tex Coord 0", "Tex Coord 1", "Tex Coord 2", "Tex Coord 3",
|
||||
"Tex Coord 4", "Tex Coord 5", "Tex Coord 6", "Tex Coord 7"};
|
||||
constexpr formatter() : EnumFormatter(names) {}
|
||||
};
|
||||
// Intended for offsetting from Color0/TexCoord0
|
||||
constexpr ShaderAttrib operator+(ShaderAttrib attrib, int offset)
|
||||
{
|
||||
return static_cast<ShaderAttrib>(static_cast<u8>(attrib) + offset);
|
||||
}
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user