Change formatting to use fmtlib (STILL NEED TO CHANGE TO FMT SYNTAX!)
This commit is contained in:
parent
c9e889723b
commit
14b9689b6d
@ -77,10 +77,10 @@ OpenGl20Renderer::OpenGl20Renderer() {
|
|||||||
throw RendererException("OpenGL 2.0 not available!");
|
throw RendererException("OpenGL 2.0 not available!");
|
||||||
|
|
||||||
Logger::info("OpenGL version: '%s' vendor: '%s' renderer: '%s' shader: '%s'",
|
Logger::info("OpenGL version: '%s' vendor: '%s' renderer: '%s' shader: '%s'",
|
||||||
glGetString(GL_VERSION),
|
(const char*)glGetString(GL_VERSION),
|
||||||
glGetString(GL_VENDOR),
|
(const char*)glGetString(GL_VENDOR),
|
||||||
glGetString(GL_RENDERER),
|
(const char*)glGetString(GL_RENDERER),
|
||||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
|
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
@ -94,7 +94,7 @@ void SteamStatisticsService::onUserStatsReceived(UserStatsReceived_t* callback)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (callback->m_eResult != k_EResultOK) {
|
if (callback->m_eResult != k_EResultOK) {
|
||||||
m_error = {strf("Steam RequestCurrentStats failed with code %d", callback->m_eResult)};
|
m_error = {strf("Steam RequestCurrentStats failed with code %d", (int)callback->m_eResult)};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ void SteamStatisticsService::onUserStatsStored(UserStatsStored_t* callback) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_error = {strf("Steam StoreStats failed with code %d", callback->m_eResult)};
|
m_error = {strf("Steam StoreStats failed with code %d", (int)callback->m_eResult)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamStatisticsService::onAchievementStored(UserAchievementStored_t* callback) {
|
void SteamStatisticsService::onAchievementStored(UserAchievementStored_t* callback) {
|
||||||
|
@ -77,4 +77,6 @@ struct hash<AssetPath> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::AssetPath> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -90,7 +90,7 @@ void Buffer::open(IOMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String Buffer::deviceName() const {
|
String Buffer::deviceName() const {
|
||||||
return strf("Buffer <%s>", this);
|
return strf("Buffer <%s>", (void*)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamOffset Buffer::size() {
|
StreamOffset Buffer::size() {
|
||||||
@ -244,7 +244,7 @@ size_t ExternalBuffer::writeAbsolute(StreamOffset, char const*, size_t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String ExternalBuffer::deviceName() const {
|
String ExternalBuffer::deviceName() const {
|
||||||
return strf("ExternalBuffer <%s>", this);
|
return strf("ExternalBuffer <%s>", (void*)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamOffset ExternalBuffer::size() {
|
StreamOffset ExternalBuffer::size() {
|
||||||
|
@ -256,4 +256,6 @@ inline size_t hash<ByteArray>::operator()(ByteArray const& b) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::ByteArray> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "StarStringView.hpp"
|
#include "StarStringView.hpp"
|
||||||
#include "StarVector.hpp"
|
#include "StarVector.hpp"
|
||||||
|
#include "StarFormat.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -103,6 +104,8 @@ public:
|
|||||||
Vec4F toRgbaF() const;
|
Vec4F toRgbaF() const;
|
||||||
Vec3F toRgbF() const;
|
Vec3F toRgbF() const;
|
||||||
|
|
||||||
|
Vec4F const& data() const;
|
||||||
|
|
||||||
Vec4F toHsva() const;
|
Vec4F toHsva() const;
|
||||||
|
|
||||||
String toHex() const;
|
String toHex() const;
|
||||||
@ -167,4 +170,6 @@ inline Vec4B Color::v4fToByte(Vec4F const& f, bool doClamp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::Color> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,6 +101,10 @@ void Directives::parse(String&& directives) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
shared = std::make_shared<Shared const>(move(newList), move(directives), prefix);
|
shared = std::make_shared<Shared const>(move(newList), move(directives), prefix);
|
||||||
|
if (view.size() < 1000) { // Pre-load short enough directives
|
||||||
|
for (auto& entry : shared->entries)
|
||||||
|
entry.loadOperation(*shared);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String Directives::string() const {
|
String Directives::string() const {
|
||||||
|
@ -8,7 +8,7 @@ namespace Star {
|
|||||||
class StarException : public std::exception {
|
class StarException : public std::exception {
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static StarException format(char const* fmt, Args const&... args);
|
static StarException format(fmt::format_string<Args...> fmt, Args const&... args);
|
||||||
|
|
||||||
StarException() noexcept;
|
StarException() noexcept;
|
||||||
virtual ~StarException() noexcept;
|
virtual ~StarException() noexcept;
|
||||||
@ -72,7 +72,7 @@ void fatalException(std::exception const& e, bool showStackTrace);
|
|||||||
class ClassName : public BaseName { \
|
class ClassName : public BaseName { \
|
||||||
public: \
|
public: \
|
||||||
template <typename... Args> \
|
template <typename... Args> \
|
||||||
static ClassName format(char const* fmt, Args const&... args) { \
|
static ClassName format(fmt::format_string<Args...> fmt, Args const&... args) { \
|
||||||
return ClassName(strf(fmt, args...)); \
|
return ClassName(strf(fmt, args...)); \
|
||||||
} \
|
} \
|
||||||
ClassName() : BaseName(#ClassName, std::string()) {} \
|
ClassName() : BaseName(#ClassName, std::string()) {} \
|
||||||
@ -91,7 +91,7 @@ STAR_EXCEPTION(IOException, StarException);
|
|||||||
STAR_EXCEPTION(MemoryException, StarException);
|
STAR_EXCEPTION(MemoryException, StarException);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
StarException StarException::format(char const* fmt, Args const&... args) {
|
StarException StarException::format(fmt::format_string<Args...> fmt, Args const&... args) {
|
||||||
return StarException(strf(fmt, args...));
|
return StarException(strf(fmt, args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "StarString_windows.hpp"
|
#include "StarString_windows.hpp"
|
||||||
|
|
||||||
#include <DbgHelp.h>
|
#include <DbgHelp.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#include "StarMemory.hpp"
|
#include "StarMemory.hpp"
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
|
#include "fmt/ostream.h"
|
||||||
|
#include "fmt/format.h"
|
||||||
|
#include "fmt/ranges.h"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
struct FormatException : public std::exception {
|
struct FormatException : public std::exception {
|
||||||
@ -17,15 +22,11 @@ struct FormatException : public std::exception {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TINYFORMAT_ERROR(reason) throw Star::FormatException(reason)
|
|
||||||
|
|
||||||
#include "tinyformat.h"
|
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... T>
|
||||||
void format(std::ostream& out, char const* fmt, Args const&... args) {
|
void format(std::ostream& out, fmt::format_string<T...> fmt, T&&... args) {
|
||||||
tinyformat::format(out, fmt, args...);
|
out << fmt::format(fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatically flushes, use format to avoid flushing.
|
// Automatically flushes, use format to avoid flushing.
|
||||||
@ -42,17 +43,20 @@ void cerrf(char const* fmt, Args const&... args) {
|
|||||||
std::cerr.flush();
|
std::cerr.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... T>
|
||||||
std::string strf(char const* fmt, Args const&... args) {
|
std::string strf(fmt::format_string<T...> fmt, T&&... args) {
|
||||||
std::ostringstream os;
|
return fmt::format(fmt, args...);
|
||||||
format(os, fmt, args...);
|
|
||||||
return os.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace OutputAnyDetail {
|
namespace OutputAnyDetail {
|
||||||
|
template<typename T, typename CharT, typename Traits>
|
||||||
|
std::basic_string<CharT, Traits> string(T const& t) {
|
||||||
|
return fmt::format("<type {} at address: {}>", typeid(T).name(), (void*)&t);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename CharT, typename Traits>
|
template<typename T, typename CharT, typename Traits>
|
||||||
std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) {
|
std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) {
|
||||||
return os << "<type " << typeid(T).name() << " at address: " << &t << ">";
|
return os << string<T, CharT, Traits>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Operator {
|
namespace Operator {
|
||||||
@ -97,4 +101,8 @@ inline std::ostream& operator<<(std::ostream& os, OutputProxy const& p) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct fmt::formatter<Star::OutputAnyDetail::Wrapper<T>> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::OutputProxy> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -130,4 +130,6 @@ std::ostream& operator<<(std::ostream& os, FormattedJson const& json);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::FormattedJson> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,4 +86,7 @@ struct hash<HostAddressWithPort> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::HostAddress> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::HostAddressWithPort> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,7 +52,7 @@ void IODevice::close() {
|
|||||||
void IODevice::sync() {}
|
void IODevice::sync() {}
|
||||||
|
|
||||||
String IODevice::deviceName() const {
|
String IODevice::deviceName() const {
|
||||||
return strf("IODevice <%s>", this);
|
return strf("IODevice <%s>", (void*)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IODevice::atEnd() {
|
bool IODevice::atEnd() {
|
||||||
|
@ -358,4 +358,7 @@ Json jsonMergeQueryDef(String const& key, Json def, Json const& first, T const&.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::Json> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::JsonObject> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef STAR_LEXICAL_CAST_HPP
|
#ifndef STAR_LEXICAL_CAST_HPP
|
||||||
#define STAR_LEXICAL_CAST_HPP
|
#define STAR_LEXICAL_CAST_HPP
|
||||||
|
|
||||||
|
#include "StarFormat.hpp"
|
||||||
#include "StarString.hpp"
|
#include "StarString.hpp"
|
||||||
#include "StarStringView.hpp"
|
#include "StarStringView.hpp"
|
||||||
#include "StarMaybe.hpp"
|
#include "StarMaybe.hpp"
|
||||||
@ -42,12 +43,8 @@ Type lexicalCast(StringView s, std::ios_base::fmtflags flags = std::ios_base::bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
std::string toString(Type const& t, std::ios_base::fmtflags flags = std::ios_base::boolalpha) {
|
std::string toString(Type const& t) {
|
||||||
std::stringstream ss;
|
return fmt::to_string(t);
|
||||||
ss.flags(flags);
|
|
||||||
ss.imbue(std::locale::classic());
|
|
||||||
ss << t;
|
|
||||||
return ss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -286,4 +286,7 @@ struct hash<Line<T, N>> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct fmt::formatter<Star::Line<T, N>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1135,4 +1135,7 @@ typename ListEnumerateTypes<Container>::Result enumerate(Container&& container)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BaseList>
|
||||||
|
struct fmt::formatter<Star::ListMixin<BaseList>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2160,4 +2160,6 @@ size_t LuaEngine::pushArguments(lua_State* state, Args const&... args) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::LuaValue> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -315,4 +315,7 @@ std::ostream& operator<<(std::ostream& os, MapMixin<BaseMap> const& m) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BaseMap>
|
||||||
|
struct fmt::formatter<Star::MapMixin<BaseMap>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -453,4 +453,7 @@ std::ostream& operator<<(std::ostream& os, Matrix3<T> m) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct fmt::formatter<Star::Matrix3<T>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -397,4 +397,7 @@ size_t hash<Maybe<T>>::operator()(Maybe<T> const& m) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct fmt::formatter<Star::Maybe<T>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -507,4 +507,7 @@ std::ostream& operator<<(std::ostream& os, MultiArray<Element, Rank> const& arra
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Element, size_t Rank>
|
||||||
|
struct fmt::formatter<Star::MultiArray<Element, Rank>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -654,4 +654,7 @@ std::ostream& operator<<(std::ostream& os, OrderedMapWrapper<Map, Key, Value, Al
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <template <typename...> class Map, typename Key, typename Value, typename Allocator, typename... MapArgs>
|
||||||
|
struct fmt::formatter<Star::OrderedMapWrapper<Map, Key, Value, Allocator, MapArgs...>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -427,4 +427,7 @@ std::ostream& operator<<(std::ostream& os, OrderedSetWrapper<Map, Value, Allocat
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <template <typename...> class Map, typename Value, typename Allocator, typename... Args>
|
||||||
|
struct fmt::formatter<Star::OrderedSetWrapper<Map, Value, Allocator, Args...>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -1073,4 +1073,7 @@ auto Box<T, N>::nearestCoordTo(Coord const& c) const -> Coord {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct fmt::formatter<Star::Box<T, N>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1136,3 +1136,7 @@ size_t hash<StringList>::operator()(StringList const& sl) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt::v10::appender fmt::formatter<Star::String>::format(Star::String const& s, format_context& ctx) const {
|
||||||
|
return formatter<std::string>::format(s.utf8(), ctx);
|
||||||
|
};
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "StarList.hpp"
|
#include "StarList.hpp"
|
||||||
#include "StarMap.hpp"
|
#include "StarMap.hpp"
|
||||||
#include "StarSet.hpp"
|
#include "StarSet.hpp"
|
||||||
|
#include "StarFormat.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -518,4 +519,8 @@ StringList StringList::sorted(Comparator&& comparator) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::String> : formatter<std::string> {
|
||||||
|
fmt::v10::appender format(Star::String const& s, format_context& ctx) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -431,3 +431,7 @@ std::ostream& operator<<(std::ostream& os, StringView const& s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt::v10::appender fmt::formatter<Star::StringView>::format(Star::StringView const& s, format_context& ctx) const {
|
||||||
|
return formatter<std::string_view>::format(s.utf8(), ctx);
|
||||||
|
};
|
@ -115,4 +115,8 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::StringView> : formatter<std::string_view> {
|
||||||
|
fmt::v10::appender format(Star::StringView const& s, format_context& ctx) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -924,4 +924,7 @@ void MVariant<Types...>::ConstRefCaller<Function>::operator()(T const& t) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename FirstType, typename... RestTypes>
|
||||||
|
struct fmt::formatter<Star::Variant<FirstType, RestTypes...>> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
9
source/extern/CMakeLists.txt
vendored
9
source/extern/CMakeLists.txt
vendored
@ -1,9 +1,17 @@
|
|||||||
INCLUDE_DIRECTORIES (
|
INCLUDE_DIRECTORIES (
|
||||||
${STAR_EXTERN_INCLUDES}
|
${STAR_EXTERN_INCLUDES}
|
||||||
|
fmt
|
||||||
lua
|
lua
|
||||||
)
|
)
|
||||||
|
|
||||||
SET (star_extern_HEADERS
|
SET (star_extern_HEADERS
|
||||||
|
fmt/core.h
|
||||||
|
fmt/format.h
|
||||||
|
fmt/format-inl.h
|
||||||
|
fmt/ostream.h
|
||||||
|
fmt/printf.h
|
||||||
|
fmt/ranges.h
|
||||||
|
fmt/std.h
|
||||||
lauxlib.h
|
lauxlib.h
|
||||||
lua.h
|
lua.h
|
||||||
lua.hpp
|
lua.hpp
|
||||||
@ -15,6 +23,7 @@ SET (star_extern_HEADERS
|
|||||||
|
|
||||||
SET (star_extern_SOURCES
|
SET (star_extern_SOURCES
|
||||||
xxhash.c
|
xxhash.c
|
||||||
|
fmt/format.cc
|
||||||
lua/lapi.c
|
lua/lapi.c
|
||||||
lua/lauxlib.c
|
lua/lauxlib.c
|
||||||
lua/lbaselib.c
|
lua/lbaselib.c
|
||||||
|
2951
source/extern/fmt/core.h
vendored
Normal file
2951
source/extern/fmt/core.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1681
source/extern/fmt/format-inl.h
vendored
Normal file
1681
source/extern/fmt/format-inl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
43
source/extern/fmt/format.cc
vendored
Normal file
43
source/extern/fmt/format.cc
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Formatting library for C++
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#include "fmt/format-inl.h"
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
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 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 thousands_sep_impl(locale_ref)
|
||||||
|
-> thousands_sep_result<char>;
|
||||||
|
template FMT_API auto decimal_point_impl(locale_ref) -> char;
|
||||||
|
|
||||||
|
template FMT_API void buffer<char>::append(const char*, const char*);
|
||||||
|
|
||||||
|
template FMT_API void vformat_to(buffer<char>&, string_view,
|
||||||
|
typename vformat_args<>::type, locale_ref);
|
||||||
|
|
||||||
|
// Explicit instantiations for wchar_t.
|
||||||
|
|
||||||
|
template FMT_API auto thousands_sep_impl(locale_ref)
|
||||||
|
-> thousands_sep_result<wchar_t>;
|
||||||
|
template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
|
||||||
|
|
||||||
|
template FMT_API void buffer<wchar_t>::append(const wchar_t*, const wchar_t*);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
FMT_END_NAMESPACE
|
4735
source/extern/fmt/format.h
vendored
Normal file
4735
source/extern/fmt/format.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
209
source/extern/fmt/ostream.h
vendored
Normal file
209
source/extern/fmt/ostream.h
vendored
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
// Formatting library for C++ - std::ostream support
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012 - present, Victor Zverovich
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#ifndef FMT_OSTREAM_H_
|
||||||
|
#define FMT_OSTREAM_H_
|
||||||
|
|
||||||
|
#include <fstream> // std::filebuf
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Generate a unique explicit instantion in every translation unit using a tag
|
||||||
|
// type in an anonymous namespace.
|
||||||
|
namespace {
|
||||||
|
struct file_access_tag {};
|
||||||
|
} // namespace
|
||||||
|
template <typename Tag, typename BufType, FILE* BufType::*FileMemberPtr>
|
||||||
|
class file_access {
|
||||||
|
friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#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* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
|
||||||
|
c_file = sfbuf->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_ostream_unicode(std::wostream&,
|
||||||
|
fmt::basic_string_view<wchar_t>) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the content of buf to os.
|
||||||
|
// 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) {
|
||||||
|
const Char* buf_data = buf.data();
|
||||||
|
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||||
|
unsigned_streamsize size = buf.size();
|
||||||
|
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
|
||||||
|
do {
|
||||||
|
unsigned_streamsize n = size <= max_size ? size : max_size;
|
||||||
|
os.write(buf_data, static_cast<std::streamsize>(n));
|
||||||
|
buf_data += n;
|
||||||
|
size -= n;
|
||||||
|
} while (size != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Char, typename T>
|
||||||
|
void format_value(buffer<Char>& buf, const T& value,
|
||||||
|
locale_ref loc = locale_ref()) {
|
||||||
|
auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
|
||||||
|
auto&& output = std::basic_ostream<Char>(&format_buf);
|
||||||
|
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||||
|
if (loc) output.imbue(loc.get<std::locale>());
|
||||||
|
#endif
|
||||||
|
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 {
|
||||||
|
auto buffer = basic_memory_buffer<Char>();
|
||||||
|
detail::format_value(buffer, value, ctx.locale());
|
||||||
|
return formatter<basic_string_view<Char>, Char>::format(
|
||||||
|
{buffer.data(), buffer.size()}, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Prints formatted data to the stream *os*.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
fmt::print(cerr, "Don't {}!", "panic");
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
FMT_MODULE_EXPORT template <typename... T>
|
||||||
|
void print(std::ostream& os, format_string<T...> fmt, T&&... 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
|
||||||
|
template <typename... Args>
|
||||||
|
void print(std::wostream& os,
|
||||||
|
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
|
||||||
|
Args&&... args) {
|
||||||
|
vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT template <typename... T>
|
||||||
|
void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
||||||
|
fmt::print(os, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename... Args>
|
||||||
|
void println(std::wostream& os,
|
||||||
|
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
|
||||||
|
Args&&... args) {
|
||||||
|
print(os, L"{}\n", fmt::format(fmt, std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // FMT_OSTREAM_H_
|
679
source/extern/fmt/printf.h
vendored
Normal file
679
source/extern/fmt/printf.h
vendored
Normal file
@ -0,0 +1,679 @@
|
|||||||
|
// Formatting library for C++ - legacy printf implementation
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#ifndef FMT_PRINTF_H_
|
||||||
|
#define FMT_PRINTF_H_
|
||||||
|
|
||||||
|
#include <algorithm> // std::max
|
||||||
|
#include <limits> // std::numeric_limits
|
||||||
|
|
||||||
|
#include "format.h"
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
FMT_BEGIN_EXPORT
|
||||||
|
|
||||||
|
template <typename T> struct printf_formatter { printf_formatter() = delete; };
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
class basic_printf_parse_context : public basic_format_parse_context<Char> {
|
||||||
|
using basic_format_parse_context<Char>::basic_format_parse_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||||
|
private:
|
||||||
|
OutputIt out_;
|
||||||
|
basic_format_args<basic_printf_context> args_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using char_type = Char;
|
||||||
|
using format_arg = basic_format_arg<basic_printf_context>;
|
||||||
|
using parse_context_type = basic_printf_parse_context<Char>;
|
||||||
|
template <typename T> using formatter_type = printf_formatter<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Constructs a ``printf_context`` object. References to the arguments are
|
||||||
|
stored in the context object so make sure they have appropriate lifetimes.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
basic_printf_context(OutputIt out,
|
||||||
|
basic_format_args<basic_printf_context> args)
|
||||||
|
: out_(out), args_(args) {}
|
||||||
|
|
||||||
|
OutputIt out() { return out_; }
|
||||||
|
void advance_to(OutputIt it) { out_ = it; }
|
||||||
|
|
||||||
|
detail::locale_ref locale() { return {}; }
|
||||||
|
|
||||||
|
format_arg arg(int id) const { return args_.get(id); }
|
||||||
|
|
||||||
|
FMT_CONSTEXPR void on_error(const char* message) {
|
||||||
|
detail::error_handler().on_error(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
|
|
||||||
|
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||||
|
// signed and unsigned integers.
|
||||||
|
template <bool IsSigned> struct int_checker {
|
||||||
|
template <typename T> static bool fits_in_int(T value) {
|
||||||
|
unsigned max = max_value<int>();
|
||||||
|
return value <= max;
|
||||||
|
}
|
||||||
|
static bool fits_in_int(bool) { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct int_checker<true> {
|
||||||
|
template <typename T> static bool fits_in_int(T value) {
|
||||||
|
return value >= (std::numeric_limits<int>::min)() &&
|
||||||
|
value <= max_value<int>();
|
||||||
|
}
|
||||||
|
static bool fits_in_int(int) { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class printf_precision_handler {
|
||||||
|
public:
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
|
int operator()(T value) {
|
||||||
|
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
||||||
|
throw_format_error("number is too big");
|
||||||
|
return (std::max)(static_cast<int>(value), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||||
|
int operator()(T) {
|
||||||
|
throw_format_error("precision is not integer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// An argument visitor that returns true iff arg is a zero integer.
|
||||||
|
class is_zero_int {
|
||||||
|
public:
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
|
bool operator()(T value) {
|
||||||
|
return value == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||||
|
bool operator()(T) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
|
||||||
|
|
||||||
|
template <> struct make_unsigned_or_bool<bool> { using type = bool; };
|
||||||
|
|
||||||
|
template <typename T, typename Context> class arg_converter {
|
||||||
|
private:
|
||||||
|
using char_type = typename Context::char_type;
|
||||||
|
|
||||||
|
basic_format_arg<Context>& arg_;
|
||||||
|
char_type type_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
arg_converter(basic_format_arg<Context>& arg, char_type type)
|
||||||
|
: arg_(arg), type_(type) {}
|
||||||
|
|
||||||
|
void operator()(bool value) {
|
||||||
|
if (type_ != 's') operator()<bool>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
|
||||||
|
void operator()(U value) {
|
||||||
|
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||||
|
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
|
||||||
|
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
||||||
|
// Extra casts are used to silence warnings.
|
||||||
|
if (is_signed) {
|
||||||
|
arg_ = detail::make_arg<Context>(
|
||||||
|
static_cast<int>(static_cast<target_type>(value)));
|
||||||
|
} else {
|
||||||
|
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||||
|
arg_ = detail::make_arg<Context>(
|
||||||
|
static_cast<unsigned>(static_cast<unsigned_type>(value)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_signed) {
|
||||||
|
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||||
|
// std::printf("%lld", -42); // prints "4294967254"
|
||||||
|
// but we don't have to do the same because it's a UB.
|
||||||
|
arg_ = detail::make_arg<Context>(static_cast<long long>(value));
|
||||||
|
} else {
|
||||||
|
arg_ = detail::make_arg<Context>(
|
||||||
|
static_cast<typename make_unsigned_or_bool<U>::type>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
|
||||||
|
void operator()(U) {} // No conversion needed for non-integral types.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Converts an integer argument to T for printf, if T is an integral type.
|
||||||
|
// If T is void, the argument is converted to corresponding signed or unsigned
|
||||||
|
// type depending on the type specifier: 'd' and 'i' - signed, other -
|
||||||
|
// unsigned).
|
||||||
|
template <typename T, typename Context, typename Char>
|
||||||
|
void convert_arg(basic_format_arg<Context>& arg, Char type) {
|
||||||
|
visit_format_arg(arg_converter<T, Context>(arg, type), arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts an integer argument to char for printf.
|
||||||
|
template <typename Context> class char_converter {
|
||||||
|
private:
|
||||||
|
basic_format_arg<Context>& arg_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
|
void operator()(T value) {
|
||||||
|
arg_ = detail::make_arg<Context>(
|
||||||
|
static_cast<typename Context::char_type>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||||
|
void operator()(T) {} // No conversion needed for non-integral types.
|
||||||
|
};
|
||||||
|
|
||||||
|
// An argument visitor that return a pointer to a C string if argument is a
|
||||||
|
// string or null otherwise.
|
||||||
|
template <typename Char> struct get_cstring {
|
||||||
|
template <typename T> const Char* operator()(T) { return nullptr; }
|
||||||
|
const Char* operator()(const Char* s) { return s; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Checks if an argument is a valid printf width specifier and sets
|
||||||
|
// left alignment if it is negative.
|
||||||
|
template <typename Char> class printf_width_handler {
|
||||||
|
private:
|
||||||
|
format_specs<Char>& specs_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit printf_width_handler(format_specs<Char>& specs) : specs_(specs) {}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||||
|
unsigned operator()(T value) {
|
||||||
|
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
|
||||||
|
if (detail::is_negative(value)) {
|
||||||
|
specs_.align = align::left;
|
||||||
|
width = 0 - width;
|
||||||
|
}
|
||||||
|
unsigned int_max = max_value<int>();
|
||||||
|
if (width > int_max) throw_format_error("number is too big");
|
||||||
|
return static_cast<unsigned>(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||||
|
unsigned operator()(T) {
|
||||||
|
throw_format_error("width is not integer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Workaround for a bug with the XL compiler when initializing
|
||||||
|
// printf_arg_formatter's base class.
|
||||||
|
template <typename Char>
|
||||||
|
auto make_arg_formatter(buffer_appender<Char> iter, format_specs<Char>& s)
|
||||||
|
-> arg_formatter<Char> {
|
||||||
|
return {iter, s, locale_ref()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ``printf`` argument formatter.
|
||||||
|
template <typename OutputIt, typename Char>
|
||||||
|
class printf_arg_formatter : public arg_formatter<Char> {
|
||||||
|
private:
|
||||||
|
using base = arg_formatter<Char>;
|
||||||
|
using context_type = basic_printf_context<OutputIt, Char>;
|
||||||
|
|
||||||
|
context_type& context_;
|
||||||
|
|
||||||
|
OutputIt write_null_pointer(bool is_string = false) {
|
||||||
|
auto s = this->specs;
|
||||||
|
s.type = presentation_type::none;
|
||||||
|
return write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
printf_arg_formatter(OutputIt iter, format_specs<Char>& s, context_type& ctx)
|
||||||
|
: base(make_arg_formatter(iter, s)), context_(ctx) {}
|
||||||
|
|
||||||
|
OutputIt operator()(monostate value) { return base::operator()(value); }
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
|
||||||
|
OutputIt operator()(T value) {
|
||||||
|
// MSVC2013 fails to compile separate overloads for bool and Char so use
|
||||||
|
// std::is_same instead.
|
||||||
|
if (std::is_same<T, Char>::value) {
|
||||||
|
format_specs<Char> fmt_specs = this->specs;
|
||||||
|
if (fmt_specs.type != presentation_type::none &&
|
||||||
|
fmt_specs.type != presentation_type::chr) {
|
||||||
|
return (*this)(static_cast<int>(value));
|
||||||
|
}
|
||||||
|
fmt_specs.sign = sign::none;
|
||||||
|
fmt_specs.alt = false;
|
||||||
|
fmt_specs.fill[0] = ' '; // Ignore '0' flag for char types.
|
||||||
|
// align::numeric needs to be overwritten here since the '0' flag is
|
||||||
|
// ignored for non-numeric types
|
||||||
|
if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
|
||||||
|
fmt_specs.align = align::right;
|
||||||
|
return write<Char>(this->out, static_cast<Char>(value), fmt_specs);
|
||||||
|
}
|
||||||
|
return base::operator()(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||||
|
OutputIt operator()(T value) {
|
||||||
|
return base::operator()(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Formats a null-terminated C string. */
|
||||||
|
OutputIt operator()(const char* value) {
|
||||||
|
if (value) return base::operator()(value);
|
||||||
|
return write_null_pointer(this->specs.type != presentation_type::pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Formats a null-terminated wide C string. */
|
||||||
|
OutputIt operator()(const wchar_t* value) {
|
||||||
|
if (value) return base::operator()(value);
|
||||||
|
return write_null_pointer(this->specs.type != presentation_type::pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputIt operator()(basic_string_view<Char> value) {
|
||||||
|
return base::operator()(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Formats a pointer. */
|
||||||
|
OutputIt operator()(const void* value) {
|
||||||
|
return value ? base::operator()(value) : write_null_pointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Formats an argument of a custom (user-defined) type. */
|
||||||
|
OutputIt operator()(typename basic_format_arg<context_type>::handle handle) {
|
||||||
|
auto parse_ctx =
|
||||||
|
basic_printf_parse_context<Char>(basic_string_view<Char>());
|
||||||
|
handle.format(parse_ctx, context_);
|
||||||
|
return this->out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
void parse_flags(format_specs<Char>& specs, const Char*& it, const Char* end) {
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
switch (*it) {
|
||||||
|
case '-':
|
||||||
|
specs.align = align::left;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
specs.sign = sign::plus;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
specs.fill[0] = '0';
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
if (specs.sign != sign::plus) {
|
||||||
|
specs.sign = sign::space;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
specs.alt = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Char, typename GetArg>
|
||||||
|
int parse_header(const Char*& it, const Char* end, format_specs<Char>& specs,
|
||||||
|
GetArg get_arg) {
|
||||||
|
int arg_index = -1;
|
||||||
|
Char c = *it;
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
// Parse an argument index (if followed by '$') or a width possibly
|
||||||
|
// preceded with '0' flag(s).
|
||||||
|
int value = parse_nonnegative_int(it, end, -1);
|
||||||
|
if (it != end && *it == '$') { // value is an argument index
|
||||||
|
++it;
|
||||||
|
arg_index = value != -1 ? value : max_value<int>();
|
||||||
|
} else {
|
||||||
|
if (c == '0') specs.fill[0] = '0';
|
||||||
|
if (value != 0) {
|
||||||
|
// Nonzero value means that we parsed width and don't need to
|
||||||
|
// parse it or flags again, so return now.
|
||||||
|
if (value == -1) throw_format_error("number is too big");
|
||||||
|
specs.width = value;
|
||||||
|
return arg_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parse_flags(specs, it, end);
|
||||||
|
// Parse width.
|
||||||
|
if (it != end) {
|
||||||
|
if (*it >= '0' && *it <= '9') {
|
||||||
|
specs.width = parse_nonnegative_int(it, end, -1);
|
||||||
|
if (specs.width == -1) throw_format_error("number is too big");
|
||||||
|
} else if (*it == '*') {
|
||||||
|
++it;
|
||||||
|
specs.width = static_cast<int>(visit_format_arg(
|
||||||
|
detail::printf_width_handler<Char>(specs), get_arg(-1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arg_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto parse_printf_presentation_type(char c, type t)
|
||||||
|
-> presentation_type {
|
||||||
|
using pt = presentation_type;
|
||||||
|
constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
|
||||||
|
switch (c) {
|
||||||
|
case 'd':
|
||||||
|
return in(t, integral_set) ? pt::dec : pt::none;
|
||||||
|
case 'o':
|
||||||
|
return in(t, integral_set) ? pt::oct : pt::none;
|
||||||
|
case 'x':
|
||||||
|
return in(t, integral_set) ? pt::hex_lower : pt::none;
|
||||||
|
case 'X':
|
||||||
|
return in(t, integral_set) ? pt::hex_upper : pt::none;
|
||||||
|
case 'a':
|
||||||
|
return in(t, float_set) ? pt::hexfloat_lower : pt::none;
|
||||||
|
case 'A':
|
||||||
|
return in(t, float_set) ? pt::hexfloat_upper : pt::none;
|
||||||
|
case 'e':
|
||||||
|
return in(t, float_set) ? pt::exp_lower : pt::none;
|
||||||
|
case 'E':
|
||||||
|
return in(t, float_set) ? pt::exp_upper : pt::none;
|
||||||
|
case 'f':
|
||||||
|
return in(t, float_set) ? pt::fixed_lower : pt::none;
|
||||||
|
case 'F':
|
||||||
|
return in(t, float_set) ? pt::fixed_upper : pt::none;
|
||||||
|
case 'g':
|
||||||
|
return in(t, float_set) ? pt::general_lower : pt::none;
|
||||||
|
case 'G':
|
||||||
|
return in(t, float_set) ? pt::general_upper : pt::none;
|
||||||
|
case 'c':
|
||||||
|
return in(t, integral_set) ? pt::chr : pt::none;
|
||||||
|
case 's':
|
||||||
|
return in(t, string_set | cstring_set) ? pt::string : pt::none;
|
||||||
|
case 'p':
|
||||||
|
return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none;
|
||||||
|
default:
|
||||||
|
return pt::none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Char, typename Context>
|
||||||
|
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||||
|
basic_format_args<Context> args) {
|
||||||
|
using iterator = buffer_appender<Char>;
|
||||||
|
auto out = iterator(buf);
|
||||||
|
auto context = basic_printf_context<iterator, Char>(out, args);
|
||||||
|
auto parse_ctx = basic_printf_parse_context<Char>(format);
|
||||||
|
|
||||||
|
// Returns the argument with specified index or, if arg_index is -1, the next
|
||||||
|
// argument.
|
||||||
|
auto get_arg = [&](int arg_index) {
|
||||||
|
if (arg_index < 0)
|
||||||
|
arg_index = parse_ctx.next_arg_id();
|
||||||
|
else
|
||||||
|
parse_ctx.check_arg_id(--arg_index);
|
||||||
|
return detail::get_arg(context, arg_index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Char* start = parse_ctx.begin();
|
||||||
|
const Char* end = parse_ctx.end();
|
||||||
|
auto it = start;
|
||||||
|
while (it != end) {
|
||||||
|
if (!find<false, Char>(it, end, '%', it)) {
|
||||||
|
it = end; // find leaves it == nullptr if it doesn't find '%'.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Char c = *it++;
|
||||||
|
if (it != end && *it == c) {
|
||||||
|
out = write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
|
||||||
|
start = ++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out =
|
||||||
|
write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start)));
|
||||||
|
|
||||||
|
auto specs = format_specs<Char>();
|
||||||
|
specs.align = align::right;
|
||||||
|
|
||||||
|
// Parse argument index, flags and width.
|
||||||
|
int arg_index = parse_header(it, end, specs, get_arg);
|
||||||
|
if (arg_index == 0) throw_format_error("argument not found");
|
||||||
|
|
||||||
|
// Parse precision.
|
||||||
|
if (it != end && *it == '.') {
|
||||||
|
++it;
|
||||||
|
c = it != end ? *it : 0;
|
||||||
|
if ('0' <= c && c <= '9') {
|
||||||
|
specs.precision = parse_nonnegative_int(it, end, 0);
|
||||||
|
} else if (c == '*') {
|
||||||
|
++it;
|
||||||
|
specs.precision = static_cast<int>(
|
||||||
|
visit_format_arg(printf_precision_handler(), get_arg(-1)));
|
||||||
|
} else {
|
||||||
|
specs.precision = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arg = get_arg(arg_index);
|
||||||
|
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
||||||
|
// specified, the '0' flag is ignored
|
||||||
|
if (specs.precision >= 0 && arg.is_integral())
|
||||||
|
specs.fill[0] =
|
||||||
|
' '; // Ignore '0' flag for non-numeric types or if '-' present.
|
||||||
|
if (specs.precision >= 0 && arg.type() == type::cstring_type) {
|
||||||
|
auto str = visit_format_arg(get_cstring<Char>(), arg);
|
||||||
|
auto str_end = str + specs.precision;
|
||||||
|
auto nul = std::find(str, str_end, Char());
|
||||||
|
arg = make_arg<basic_printf_context<iterator, Char>>(
|
||||||
|
basic_string_view<Char>(
|
||||||
|
str, to_unsigned(nul != str_end ? nul - str : specs.precision)));
|
||||||
|
}
|
||||||
|
if (specs.alt && visit_format_arg(is_zero_int(), arg)) specs.alt = false;
|
||||||
|
if (specs.fill[0] == '0') {
|
||||||
|
if (arg.is_arithmetic() && specs.align != align::left)
|
||||||
|
specs.align = align::numeric;
|
||||||
|
else
|
||||||
|
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types or if '-'
|
||||||
|
// flag is also present.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse length and convert the argument to the required type.
|
||||||
|
c = it != end ? *it++ : 0;
|
||||||
|
Char t = it != end ? *it : 0;
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
if (t == 'h') {
|
||||||
|
++it;
|
||||||
|
t = it != end ? *it : 0;
|
||||||
|
convert_arg<signed char>(arg, t);
|
||||||
|
} else {
|
||||||
|
convert_arg<short>(arg, t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (t == 'l') {
|
||||||
|
++it;
|
||||||
|
t = it != end ? *it : 0;
|
||||||
|
convert_arg<long long>(arg, t);
|
||||||
|
} else {
|
||||||
|
convert_arg<long>(arg, t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
convert_arg<intmax_t>(arg, t);
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
convert_arg<size_t>(arg, t);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
convert_arg<std::ptrdiff_t>(arg, t);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
// printf produces garbage when 'L' is omitted for long double, no
|
||||||
|
// need to do the same.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
--it;
|
||||||
|
convert_arg<void>(arg, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse type.
|
||||||
|
if (it == end) throw_format_error("invalid format string");
|
||||||
|
char type = static_cast<char>(*it++);
|
||||||
|
if (arg.is_integral()) {
|
||||||
|
// Normalize type.
|
||||||
|
switch (type) {
|
||||||
|
case 'i':
|
||||||
|
case 'u':
|
||||||
|
type = 'd';
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
visit_format_arg(
|
||||||
|
char_converter<basic_printf_context<iterator, Char>>(arg), arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specs.type = parse_printf_presentation_type(type, arg.type());
|
||||||
|
if (specs.type == presentation_type::none)
|
||||||
|
throw_format_error("invalid format specifier");
|
||||||
|
|
||||||
|
start = it;
|
||||||
|
|
||||||
|
// Format argument.
|
||||||
|
out = visit_format_arg(
|
||||||
|
printf_arg_formatter<iterator, Char>(out, specs, context), arg);
|
||||||
|
}
|
||||||
|
write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
|
||||||
|
}
|
||||||
|
FMT_END_DETAIL_NAMESPACE
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
using basic_printf_context_t =
|
||||||
|
basic_printf_context<detail::buffer_appender<Char>, Char>;
|
||||||
|
|
||||||
|
using printf_context = basic_printf_context_t<char>;
|
||||||
|
using wprintf_context = basic_printf_context_t<wchar_t>;
|
||||||
|
|
||||||
|
using printf_args = basic_format_args<printf_context>;
|
||||||
|
using wprintf_args = basic_format_args<wprintf_context>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Constructs an `~fmt::format_arg_store` object that contains references to
|
||||||
|
arguments and can be implicitly converted to `~fmt::printf_args`.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename... T>
|
||||||
|
inline auto make_printf_args(const T&... args)
|
||||||
|
-> format_arg_store<printf_context, T...> {
|
||||||
|
return {args...};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Constructs an `~fmt::format_arg_store` object that contains references to
|
||||||
|
arguments and can be implicitly converted to `~fmt::wprintf_args`.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename... T>
|
||||||
|
inline auto make_wprintf_args(const T&... args)
|
||||||
|
-> format_arg_store<wprintf_context, T...> {
|
||||||
|
return {args...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename Char = char_t<S>>
|
||||||
|
inline auto vsprintf(
|
||||||
|
const S& fmt,
|
||||||
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||||
|
-> std::basic_string<Char> {
|
||||||
|
auto buf = basic_memory_buffer<Char>();
|
||||||
|
detail::vprintf(buf, detail::to_string_view(fmt), args);
|
||||||
|
return to_string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Formats arguments and returns the result as a string.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
std::string message = fmt::sprintf("The answer is %d", 42);
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
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(detail::to_string_view(fmt),
|
||||||
|
fmt::make_format_args<context>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename Char = char_t<S>>
|
||||||
|
inline auto vfprintf(
|
||||||
|
std::FILE* f, const S& fmt,
|
||||||
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||||
|
-> int {
|
||||||
|
auto buf = basic_memory_buffer<Char>();
|
||||||
|
detail::vprintf(buf, detail::to_string_view(fmt), args);
|
||||||
|
size_t size = buf.size();
|
||||||
|
return std::fwrite(buf.data(), sizeof(Char), size, f) < size
|
||||||
|
? -1
|
||||||
|
: static_cast<int>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Prints formatted data to the file *f*.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
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, detail::to_string_view(fmt),
|
||||||
|
fmt::make_format_args<context>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S, typename Char = char_t<S>>
|
||||||
|
inline auto vprintf(
|
||||||
|
const S& fmt,
|
||||||
|
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
|
||||||
|
-> int {
|
||||||
|
return vfprintf(stdout, detail::to_string_view(fmt), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Prints formatted data to ``stdout``.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
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(
|
||||||
|
detail::to_string_view(fmt),
|
||||||
|
fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_END_EXPORT
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // FMT_PRINTF_H_
|
732
source/extern/fmt/ranges.h
vendored
Normal file
732
source/extern/fmt/ranges.h
vendored
Normal file
@ -0,0 +1,732 @@
|
|||||||
|
// Formatting library for C++ - experimental range support
|
||||||
|
//
|
||||||
|
// Copyright (c) 2012 - present, Victor Zverovich
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// For the license information refer to format.h.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
|
||||||
|
// All Rights Reserved
|
||||||
|
// {fmt} support for ranges, containers and types tuple interface.
|
||||||
|
|
||||||
|
#ifndef FMT_RANGES_H_
|
||||||
|
#define FMT_RANGES_H_
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "format.h"
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename Range, typename OutputIt>
|
||||||
|
auto copy(const Range& range, OutputIt out) -> OutputIt {
|
||||||
|
for (auto it = range.begin(), end = range.end(); it != end; ++it)
|
||||||
|
*out++ = *it;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt>
|
||||||
|
auto copy(const char* str, OutputIt out) -> OutputIt {
|
||||||
|
while (*str) *out++ = *str++;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt> auto copy(char ch, OutputIt out) -> OutputIt {
|
||||||
|
*out++ = ch;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt> auto copy(wchar_t ch, OutputIt out) -> OutputIt {
|
||||||
|
*out++ = ch;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if T has a std::string-like interface, like std::string_view.
|
||||||
|
template <typename T> class is_std_string_like {
|
||||||
|
template <typename U>
|
||||||
|
static auto check(U* p)
|
||||||
|
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
|
||||||
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T> class is_map {
|
||||||
|
template <typename U> static auto check(U*) -> typename U::mapped_type;
|
||||||
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef FMT_FORMAT_MAP_AS_LIST // DEPRECATED!
|
||||||
|
static constexpr const bool value = false;
|
||||||
|
#else
|
||||||
|
static constexpr const bool value =
|
||||||
|
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> class is_set {
|
||||||
|
template <typename U> static auto check(U*) -> typename U::key_type;
|
||||||
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef FMT_FORMAT_SET_AS_LIST // DEPRECATED!
|
||||||
|
static constexpr const bool value = false;
|
||||||
|
#else
|
||||||
|
static constexpr const bool value =
|
||||||
|
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Ts> struct conditional_helper {};
|
||||||
|
|
||||||
|
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
||||||
|
|
||||||
|
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
|
||||||
|
|
||||||
|
# define FMT_DECLTYPE_RETURN(val) \
|
||||||
|
->decltype(val) { return val; } \
|
||||||
|
static_assert( \
|
||||||
|
true, "") // This makes it so that a semicolon is required after the
|
||||||
|
// macro, which helps clang-format handle the formatting.
|
||||||
|
|
||||||
|
// C array overload
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
auto range_begin(const T (&arr)[N]) -> const T* {
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
auto range_end(const T (&arr)[N]) -> const T* {
|
||||||
|
return arr + N;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct has_member_fn_begin_end_t : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
|
||||||
|
decltype(std::declval<T>().end())>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
// Member function overload
|
||||||
|
template <typename T>
|
||||||
|
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
|
||||||
|
template <typename T>
|
||||||
|
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
|
||||||
|
|
||||||
|
// ADL overload. Only participates in overload resolution if member functions
|
||||||
|
// are not found.
|
||||||
|
template <typename T>
|
||||||
|
auto range_begin(T&& rng)
|
||||||
|
-> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
|
||||||
|
decltype(begin(static_cast<T&&>(rng)))> {
|
||||||
|
return begin(static_cast<T&&>(rng));
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
|
||||||
|
decltype(end(static_cast<T&&>(rng)))> {
|
||||||
|
return end(static_cast<T&&>(rng));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct has_const_begin_end : std::false_type {};
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct has_mutable_begin_end : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_const_begin_end<
|
||||||
|
T,
|
||||||
|
void_t<
|
||||||
|
decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
|
||||||
|
decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_mutable_begin_end<
|
||||||
|
T, void_t<decltype(detail::range_begin(std::declval<T>())),
|
||||||
|
decltype(detail::range_end(std::declval<T>())),
|
||||||
|
// the extra int here is because older versions of MSVC don't
|
||||||
|
// SFINAE properly unless there are distinct types
|
||||||
|
int>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_range_<T, void>
|
||||||
|
: std::integral_constant<bool, (has_const_begin_end<T>::value ||
|
||||||
|
has_mutable_begin_end<T>::value)> {};
|
||||||
|
# undef FMT_DECLTYPE_RETURN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// tuple_size and tuple_element check.
|
||||||
|
template <typename T> class is_tuple_like_ {
|
||||||
|
template <typename U>
|
||||||
|
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
|
||||||
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
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_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...>;
|
||||||
|
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
|
||||||
|
#else
|
||||||
|
template <typename T, T... N> struct integer_sequence {
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
|
||||||
|
|
||||||
|
template <typename T, size_t N, T... Ns>
|
||||||
|
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
||||||
|
template <typename T, T... Ns>
|
||||||
|
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
||||||
|
|
||||||
|
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... Is>
|
||||||
|
static std::true_type check2(index_sequence<Is...>,
|
||||||
|
integer_sequence<bool, (Is == Is)...>);
|
||||||
|
static std::false_type check2(...);
|
||||||
|
template <std::size_t... Is>
|
||||||
|
static decltype(check2(
|
||||||
|
index_sequence<Is...>{},
|
||||||
|
integer_sequence<
|
||||||
|
bool, (is_formattable<typename std::tuple_element<Is, T>::type,
|
||||||
|
C>::value)...>{})) check(index_sequence<Is...>);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const bool value =
|
||||||
|
decltype(check(tuple_index_sequence<T>{}))::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tuple, typename F, size_t... Is>
|
||||||
|
FMT_CONSTEXPR void for_each(index_sequence<Is...>, Tuple&& t, F&& f) {
|
||||||
|
using std::get;
|
||||||
|
// Using a free function get<Is>(Tuple) now.
|
||||||
|
const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
|
||||||
|
ignore_unused(unused);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tuple, typename F>
|
||||||
|
FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) {
|
||||||
|
for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
|
||||||
|
std::forward<Tuple>(t), std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tuple1, typename Tuple2, typename F, size_t... Is>
|
||||||
|
void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
|
||||||
|
using std::get;
|
||||||
|
const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
|
||||||
|
ignore_unused(unused);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tuple1, typename Tuple2, typename F>
|
||||||
|
void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
|
||||||
|
for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
|
||||||
|
std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
|
||||||
|
std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace tuple {
|
||||||
|
// Workaround a bug in MSVC 2019 (v140).
|
||||||
|
template <typename Char, typename... T>
|
||||||
|
using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
|
||||||
|
|
||||||
|
using std::get;
|
||||||
|
template <typename Tuple, typename Char, std::size_t... Is>
|
||||||
|
auto get_formatters(index_sequence<Is...>)
|
||||||
|
-> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
|
||||||
|
} // namespace tuple
|
||||||
|
|
||||||
|
#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&>()));
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
|
||||||
|
using type = T&;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using range_reference_type = typename range_reference_type_impl<T>::type;
|
||||||
|
#else
|
||||||
|
template <typename Range>
|
||||||
|
using range_reference_type =
|
||||||
|
decltype(*detail::range_begin(std::declval<Range&>()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We don't use the Range's value_type for anything, but we do need the Range's
|
||||||
|
// reference type, with cv-ref stripped.
|
||||||
|
template <typename Range>
|
||||||
|
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
|
||||||
|
|
||||||
|
template <typename Formatter>
|
||||||
|
FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
|
||||||
|
-> decltype(f.set_debug_format(set)) {
|
||||||
|
f.set_debug_format(set);
|
||||||
|
}
|
||||||
|
template <typename Formatter>
|
||||||
|
FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
|
||||||
|
|
||||||
|
// These are not generic lambdas for compatibility with C++11.
|
||||||
|
template <typename ParseContext> struct parse_empty_specs {
|
||||||
|
template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
|
||||||
|
f.parse(ctx);
|
||||||
|
detail::maybe_set_debug_format(f, true);
|
||||||
|
}
|
||||||
|
ParseContext& ctx;
|
||||||
|
};
|
||||||
|
template <typename FormatContext> struct format_tuple_element {
|
||||||
|
using char_type = typename FormatContext::char_type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void operator()(const formatter<T, char_type>& f, const T& v) {
|
||||||
|
if (i > 0)
|
||||||
|
ctx.advance_to(detail::copy_str<char_type>(separator, ctx.out()));
|
||||||
|
ctx.advance_to(f.format(v, ctx));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
FormatContext& ctx;
|
||||||
|
basic_string_view<char_type> separator;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T> struct is_tuple_like {
|
||||||
|
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 Tuple, typename Char>
|
||||||
|
struct formatter<Tuple, Char,
|
||||||
|
enable_if_t<fmt::is_tuple_like<Tuple>::value &&
|
||||||
|
fmt::is_tuple_formattable<Tuple, Char>::value>> {
|
||||||
|
private:
|
||||||
|
decltype(detail::tuple::get_formatters<Tuple, Char>(
|
||||||
|
detail::tuple_index_sequence<Tuple>())) formatters_;
|
||||||
|
|
||||||
|
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, ')'>{};
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
auto it = ctx.begin();
|
||||||
|
if (it != ctx.end() && *it != '}')
|
||||||
|
FMT_THROW(format_error("invalid format specifier"));
|
||||||
|
detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const Tuple& value, FormatContext& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
ctx.advance_to(detail::copy_str<Char>(opening_bracket_, ctx.out()));
|
||||||
|
detail::for_each2(
|
||||||
|
formatters_, value,
|
||||||
|
detail::format_tuple_element<FormatContext>{0, ctx, separator_});
|
||||||
|
return detail::copy_str<Char>(closing_bracket_, ctx.out());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Char> struct is_range {
|
||||||
|
static constexpr const bool value =
|
||||||
|
detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
|
||||||
|
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
||||||
|
!std::is_convertible<T, detail::std_string_view<Char>>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename Context> struct range_mapper {
|
||||||
|
using mapper = arg_mapper<Context>;
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||||
|
static auto map(T&& value) -> T&& {
|
||||||
|
return static_cast<T&&>(value);
|
||||||
|
}
|
||||||
|
template <typename T,
|
||||||
|
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||||
|
static auto map(T&& value)
|
||||||
|
-> decltype(mapper().map(static_cast<T&&>(value))) {
|
||||||
|
return mapper().map(static_cast<T&&>(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Char, typename Element>
|
||||||
|
using range_formatter_type =
|
||||||
|
formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
|
||||||
|
std::declval<Element>()))>,
|
||||||
|
Char>;
|
||||||
|
|
||||||
|
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
|
||||||
|
: is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
|
||||||
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename Char, typename Enable = void>
|
||||||
|
struct range_formatter;
|
||||||
|
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct range_formatter<
|
||||||
|
T, Char,
|
||||||
|
enable_if_t<conjunction<std::is_same<T, remove_cvref_t<T>>,
|
||||||
|
is_formattable<T, Char>>::value>> {
|
||||||
|
private:
|
||||||
|
detail::range_formatter_type<Char, T> underlying_;
|
||||||
|
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, ']'>{};
|
||||||
|
|
||||||
|
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 == 'n') {
|
||||||
|
set_brackets({}, {});
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it != end && *it != '}') {
|
||||||
|
if (*it != ':') FMT_THROW(format_error("invalid format specifier"));
|
||||||
|
++it;
|
||||||
|
} else {
|
||||||
|
detail::maybe_set_debug_format(underlying_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.advance_to(it);
|
||||||
|
return underlying_.parse(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename FormatContext>
|
||||||
|
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||||
|
detail::range_mapper<buffer_context<Char>> mapper;
|
||||||
|
auto out = ctx.out();
|
||||||
|
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::copy_str<Char>(separator_, out);
|
||||||
|
ctx.advance_to(out);
|
||||||
|
out = underlying_.format(mapper.map(*it), ctx);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
out = detail::copy_str<Char>(closing_bracket_, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class range_format { disabled, map, set, sequence, string, debug_string };
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
struct range_format_kind_
|
||||||
|
: std::integral_constant<range_format,
|
||||||
|
std::is_same<uncvref_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, '}'>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
const std::tuple<T...>& tuple;
|
||||||
|
basic_string_view<Char> sep;
|
||||||
|
|
||||||
|
tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
|
||||||
|
: tuple(t), sep{s} {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
|
||||||
|
// support in tuple_join. It is disabled by default because of issues with
|
||||||
|
// the dynamic width and precision.
|
||||||
|
#ifndef FMT_TUPLE_JOIN_SPECIFIERS
|
||||||
|
# define FMT_TUPLE_JOIN_SPECIFIERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename Char, typename... T>
|
||||||
|
struct formatter<tuple_join_view<Char, T...>, Char> {
|
||||||
|
template <typename ParseContext>
|
||||||
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const tuple_join_view<Char, T...>& value,
|
||||||
|
FormatContext& ctx) const -> typename FormatContext::iterator {
|
||||||
|
return do_format(value, ctx,
|
||||||
|
std::integral_constant<size_t, sizeof...(T)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
|
||||||
|
|
||||||
|
template <typename ParseContext>
|
||||||
|
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
|
||||||
|
std::integral_constant<size_t, 0>)
|
||||||
|
-> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ParseContext, size_t N>
|
||||||
|
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
|
||||||
|
std::integral_constant<size_t, N>)
|
||||||
|
-> decltype(ctx.begin()) {
|
||||||
|
auto end = ctx.begin();
|
||||||
|
#if FMT_TUPLE_JOIN_SPECIFIERS
|
||||||
|
end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
|
||||||
|
if (N > 1) {
|
||||||
|
auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
|
||||||
|
if (end != end1)
|
||||||
|
FMT_THROW(format_error("incompatible format specs for tuple elements"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
|
||||||
|
std::integral_constant<size_t, 0>) const ->
|
||||||
|
typename FormatContext::iterator {
|
||||||
|
return ctx.out();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext, size_t N>
|
||||||
|
auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
|
||||||
|
std::integral_constant<size_t, N>) const ->
|
||||||
|
typename FormatContext::iterator {
|
||||||
|
auto out = std::get<sizeof...(T) - N>(formatters_)
|
||||||
|
.format(std::get<sizeof...(T) - N>(value.tuple), ctx);
|
||||||
|
if (N > 1) {
|
||||||
|
out = std::copy(value.sep.begin(), value.sep.end(), out);
|
||||||
|
ctx.advance_to(out);
|
||||||
|
return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
// Check if T has an interface like a container adaptor (e.g. std::stack,
|
||||||
|
// std::queue, std::priority_queue).
|
||||||
|
template <typename T> class is_container_adaptor_like {
|
||||||
|
template <typename U> static auto check(U* p) -> typename U::container_type;
|
||||||
|
template <typename> static void check(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const bool value =
|
||||||
|
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Container> struct all {
|
||||||
|
const Container& c;
|
||||||
|
auto begin() const -> typename Container::const_iterator { return c.begin(); }
|
||||||
|
auto end() const -> typename Container::const_iterator { return c.end(); }
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct formatter<T, Char,
|
||||||
|
enable_if_t<detail::is_container_adaptor_like<T>::value>>
|
||||||
|
: formatter<detail::all<typename T::container_type>, Char> {
|
||||||
|
using all = detail::all<typename T::container_type>;
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||||
|
struct getter : T {
|
||||||
|
static auto get(const T& t) -> all {
|
||||||
|
return {t.*(&getter::c)}; // Access c through the derived class.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return formatter<all>::format(getter::get(t), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_BEGIN_EXPORT
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Returns an object that formats `tuple` with elements separated by `sep`.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
std::tuple<int, char> t = {1, 'a'};
|
||||||
|
fmt::print("{}", fmt::join(t, ", "));
|
||||||
|
// Output: "1, a"
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename... T>
|
||||||
|
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
|
||||||
|
-> tuple_join_view<char, T...> {
|
||||||
|
return {tuple, sep};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
|
||||||
|
basic_string_view<wchar_t> sep)
|
||||||
|
-> tuple_join_view<wchar_t, T...> {
|
||||||
|
return {tuple, sep};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Returns an object that formats `initializer_list` with elements separated by
|
||||||
|
`sep`.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
fmt::print("{}", fmt::join({1, 2, 3}, ", "));
|
||||||
|
// Output: "1, 2, 3"
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
auto join(std::initializer_list<T> list, string_view sep)
|
||||||
|
-> join_view<const T*, const T*> {
|
||||||
|
return join(std::begin(list), std::end(list), sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
FMT_END_EXPORT
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // FMT_RANGES_H_
|
349
source/extern/fmt/std.h
vendored
Normal file
349
source/extern/fmt/std.h
vendored
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
// 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 <cstdlib>
|
||||||
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <typeinfo>
|
||||||
|
#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
|
||||||
|
# if FMT_HAS_INCLUDE(<optional>)
|
||||||
|
# include <optional>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GCC 4 does not support FMT_HAS_INCLUDE.
|
||||||
|
#if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
|
||||||
|
# include <cxxabi.h>
|
||||||
|
// Android NDK with gabi++ library on some architectures does not implement
|
||||||
|
// abi::__cxa_demangle().
|
||||||
|
# ifndef __GABIXX_CXXABI_H__
|
||||||
|
# define FMT_HAS_ABI_CXA_DEMANGLE
|
||||||
|
# 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>(memory_buffer& quoted,
|
||||||
|
const std::filesystem::path& p) {
|
||||||
|
auto buf = basic_memory_buffer<wchar_t>();
|
||||||
|
write_escaped_string<wchar_t>(std::back_inserter(buf), p.native());
|
||||||
|
// Convert UTF-16 to UTF-8.
|
||||||
|
if (!unicode_to_utf8<wchar_t>::convert(quoted, {buf.data(), buf.size()}))
|
||||||
|
FMT_THROW(std::runtime_error("invalid utf16"));
|
||||||
|
}
|
||||||
|
# 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
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename Char>
|
||||||
|
struct formatter<std::filesystem::path, Char>
|
||||||
|
: formatter<basic_string_view<Char>> {
|
||||||
|
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
|
||||||
|
auto out = formatter<basic_string_view<Char>>::parse(ctx);
|
||||||
|
this->set_debug_format(false);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const std::filesystem::path& p, FormatContext& ctx) const ->
|
||||||
|
typename FormatContext::iterator {
|
||||||
|
auto quoted = basic_memory_buffer<Char>();
|
||||||
|
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
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename Char>
|
||||||
|
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_optional
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct formatter<std::optional<T>, Char,
|
||||||
|
std::enable_if_t<is_formattable<T, Char>::value>> {
|
||||||
|
private:
|
||||||
|
formatter<T, Char> underlying_;
|
||||||
|
static constexpr basic_string_view<Char> optional =
|
||||||
|
detail::string_literal<Char, 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
|
||||||
|
'('>{};
|
||||||
|
static constexpr basic_string_view<Char> none =
|
||||||
|
detail::string_literal<Char, 'n', 'o', 'n', 'e'>{};
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set)
|
||||||
|
-> decltype(u.set_debug_format(set)) {
|
||||||
|
u.set_debug_format(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
|
||||||
|
maybe_set_debug_format(underlying_, true);
|
||||||
|
return underlying_.parse(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(std::optional<T> const& opt, FormatContext& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
if (!opt) return detail::write<Char>(ctx.out(), none);
|
||||||
|
|
||||||
|
auto out = ctx.out();
|
||||||
|
out = detail::write<Char>(out, optional);
|
||||||
|
ctx.advance_to(out);
|
||||||
|
out = underlying_.format(*opt, ctx);
|
||||||
|
return detail::write(out, ')');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
#endif // __cpp_lib_optional
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_variant
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
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>;
|
||||||
|
|
||||||
|
template <typename> struct is_variant_like_ : std::false_type {};
|
||||||
|
template <typename... Types>
|
||||||
|
struct is_variant_like_<std::variant<Types...>> : std::true_type {};
|
||||||
|
|
||||||
|
// formattable element check.
|
||||||
|
template <typename T, typename C> class is_variant_formattable_ {
|
||||||
|
template <std::size_t... Is>
|
||||||
|
static std::conjunction<
|
||||||
|
is_formattable<std::variant_alternative_t<Is, T>, C>...>
|
||||||
|
check(std::index_sequence<Is...>);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
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(");
|
||||||
|
try {
|
||||||
|
std::visit(
|
||||||
|
[&](const auto& v) {
|
||||||
|
out = detail::write_variant_alternative<Char>(out, v);
|
||||||
|
},
|
||||||
|
value);
|
||||||
|
} catch (const std::bad_variant_access&) {
|
||||||
|
detail::write<Char>(out, "valueless by exception");
|
||||||
|
}
|
||||||
|
*out++ = ')';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
#endif // __cpp_lib_variant
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename Char> struct formatter<std::error_code, Char> {
|
||||||
|
template <typename ParseContext>
|
||||||
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
auto out = ctx.out();
|
||||||
|
out = detail::write_bytes(out, ec.category().name(), format_specs<Char>());
|
||||||
|
out = detail::write<Char>(out, Char(':'));
|
||||||
|
out = detail::write<Char>(out, ec.value());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_MODULE_EXPORT
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct formatter<
|
||||||
|
T, Char,
|
||||||
|
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
|
||||||
|
private:
|
||||||
|
bool with_typename_ = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||||
|
-> decltype(ctx.begin()) {
|
||||||
|
auto it = ctx.begin();
|
||||||
|
auto end = ctx.end();
|
||||||
|
if (it == end || *it == '}') return it;
|
||||||
|
if (*it == 't') {
|
||||||
|
++it;
|
||||||
|
with_typename_ = true;
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt>
|
||||||
|
auto format(const std::exception& ex,
|
||||||
|
basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
|
||||||
|
format_specs<Char> spec;
|
||||||
|
auto out = ctx.out();
|
||||||
|
if (!with_typename_)
|
||||||
|
return detail::write_bytes(out, string_view(ex.what()), spec);
|
||||||
|
|
||||||
|
const std::type_info& ti = typeid(ex);
|
||||||
|
#ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
||||||
|
int status = 0;
|
||||||
|
std::size_t size = 0;
|
||||||
|
std::unique_ptr<char, decltype(&std::free)> demangled_name_ptr(
|
||||||
|
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
|
||||||
|
|
||||||
|
string_view demangled_name_view;
|
||||||
|
if (demangled_name_ptr) {
|
||||||
|
demangled_name_view = demangled_name_ptr.get();
|
||||||
|
|
||||||
|
// Normalization of stdlib inline namespace names.
|
||||||
|
// libc++ inline namespaces.
|
||||||
|
// std::__1::* -> std::*
|
||||||
|
// std::__1::__fs::* -> std::*
|
||||||
|
// libstdc++ inline namespaces.
|
||||||
|
// std::__cxx11::* -> std::*
|
||||||
|
// std::filesystem::__cxx11::* -> std::filesystem::*
|
||||||
|
if (demangled_name_view.starts_with("std::")) {
|
||||||
|
char* begin = demangled_name_ptr.get();
|
||||||
|
char* to = begin + 5; // std::
|
||||||
|
for (char *from = to, *end = begin + demangled_name_view.size();
|
||||||
|
from < end;) {
|
||||||
|
// This is safe, because demangled_name is NUL-terminated.
|
||||||
|
if (from[0] == '_' && from[1] == '_') {
|
||||||
|
char* next = from + 1;
|
||||||
|
while (next < end && *next != ':') next++;
|
||||||
|
if (next[0] == ':' && next[1] == ':') {
|
||||||
|
from = next + 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*to++ = *from++;
|
||||||
|
}
|
||||||
|
demangled_name_view = {begin, detail::to_unsigned(to - begin)};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
demangled_name_view = string_view(ti.name());
|
||||||
|
}
|
||||||
|
out = detail::write_bytes(out, demangled_name_view, spec);
|
||||||
|
#elif FMT_MSC_VERSION
|
||||||
|
string_view demangled_name_view(ti.name());
|
||||||
|
if (demangled_name_view.starts_with("class "))
|
||||||
|
demangled_name_view.remove_prefix(6);
|
||||||
|
else if (demangled_name_view.starts_with("struct "))
|
||||||
|
demangled_name_view.remove_prefix(7);
|
||||||
|
out = detail::write_bytes(out, demangled_name_view, spec);
|
||||||
|
#else
|
||||||
|
out = detail::write_bytes(out, string_view(ti.name()), spec);
|
||||||
|
#endif
|
||||||
|
out = detail::write<Char>(out, Char(':'));
|
||||||
|
out = detail::write<Char>(out, Char(' '));
|
||||||
|
out = detail::write_bytes(out, string_view(ex.what()), spec);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // FMT_STD_H_
|
@ -1302,7 +1302,7 @@ Maybe<bool> PathController::move(ActorMovementController& movementController, Ac
|
|||||||
float angleFactor = movementController.velocity().normalized() * delta.normalized();
|
float angleFactor = movementController.velocity().normalized() * delta.normalized();
|
||||||
float speedAlongAngle = angleFactor * movementController.velocity().magnitude();
|
float speedAlongAngle = angleFactor * movementController.velocity().magnitude();
|
||||||
auto acc = parameters.airForce.value(0.0) / movementController.mass();
|
auto acc = parameters.airForce.value(0.0) / movementController.mass();
|
||||||
sourceVelocity = delta.normalized() * fmin(parameters.flySpeed.value(0.0), speedAlongAngle + acc * WorldTimestep);;
|
sourceVelocity = delta.normalized() * fmin(parameters.flySpeed.value(0.0), speedAlongAngle + acc * WorldTimestep);
|
||||||
targetVelocity = sourceVelocity;
|
targetVelocity = sourceVelocity;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -93,4 +93,6 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::CelestialCoordinate> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1025,7 +1025,7 @@ String Humanoid::frameBase(State state) const {
|
|||||||
return "lay";
|
return "lay";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw StarException(strf("No such state '%s'", state));
|
throw StarException(strf("No such state '%s'", StateNames.getRight(state)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,4 +57,6 @@ static uint8_t const EssentialItemCount = 4;
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::InventorySlot> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -79,4 +79,6 @@ struct hash<ItemDescriptor> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::ItemDescriptor> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,4 +35,6 @@ struct hash<ItemRecipe> {
|
|||||||
std::ostream& operator<<(std::ostream& os, ItemRecipe const& recipe);
|
std::ostream& operator<<(std::ostream& os, ItemRecipe const& recipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::ItemRecipe> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -147,4 +147,8 @@ inline bool operator!=(Parameters const& lhs, Parameters const& rhs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::PlatformerAStar::Node> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::PlatformerAStar::Action> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::PlatformerAStar::Edge> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -503,7 +503,7 @@ List<Songbook::Note> Songbook::parseABC(String const& abc) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw StarException(strf("Unrecognized note %s", head));
|
throw StarException(strf("Unrecognized note %s", (char)head));
|
||||||
}
|
}
|
||||||
if (note != 0) {
|
if (note != 0) {
|
||||||
bool accidentalActive = accidentalSpecified;
|
bool accidentalActive = accidentalSpecified;
|
||||||
@ -556,7 +556,7 @@ List<Songbook::Note> Songbook::parseABC(String const& abc) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw StarException(strf("Unrecognized note %s", head));
|
throw StarException(strf("Unrecognized note %s", (char)head));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,22 @@ WorldId parseWorldId(String const& printedId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, CelestialWorldId const& worldId) {
|
||||||
|
os << printWorldId(worldId);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, ClientShipWorldId const& worldId) {
|
||||||
|
os << printWorldId(worldId);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, InstanceWorldId const& worldId) {
|
||||||
|
os << printWorldId(worldId);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, WorldId const& worldId) {
|
std::ostream& operator<<(std::ostream& os, WorldId const& worldId) {
|
||||||
os << printWorldId(worldId);
|
os << printWorldId(worldId);
|
||||||
return os;
|
return os;
|
||||||
@ -135,7 +151,7 @@ String printSpawnTarget(SpawnTarget spawnTarget) {
|
|||||||
else if (auto pos = spawnTarget.ptr<SpawnTargetPosition>())
|
else if (auto pos = spawnTarget.ptr<SpawnTargetPosition>())
|
||||||
return strf("%s.%s", (*pos)[0], (*pos)[1]);
|
return strf("%s.%s", (*pos)[0], (*pos)[1]);
|
||||||
else if (auto x = spawnTarget.ptr<SpawnTargetX>())
|
else if (auto x = spawnTarget.ptr<SpawnTargetX>())
|
||||||
return toString(*x);
|
return toString(x->t);
|
||||||
else
|
else
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,9 @@ String printWorldId(WorldId const& worldId);
|
|||||||
WorldId parseWorldId(String const& printedId);
|
WorldId parseWorldId(String const& printedId);
|
||||||
|
|
||||||
// Same as outputting printWorldId
|
// Same as outputting printWorldId
|
||||||
|
std::ostream& operator<<(std::ostream& os, CelestialWorldId const& worldId);
|
||||||
|
std::ostream& operator<<(std::ostream& os, ClientShipWorldId const& worldId);
|
||||||
|
std::ostream& operator<<(std::ostream& os, InstanceWorldId const& worldId);
|
||||||
std::ostream& operator<<(std::ostream& os, WorldId const& worldId);
|
std::ostream& operator<<(std::ostream& os, WorldId const& worldId);
|
||||||
|
|
||||||
strong_typedef(String, SpawnTargetUniqueEntity);
|
strong_typedef(String, SpawnTargetUniqueEntity);
|
||||||
@ -88,4 +91,10 @@ DataStream& operator<<(DataStream& ds, WarpToWorld const& warpToWorld);
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::CelestialWorldId> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::ClientShipWorldId> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::InstanceWorldId> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::WorldId> : ostream_formatter {};
|
||||||
|
template <> struct fmt::formatter<Star::WarpToWorld> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -162,7 +162,24 @@ TerrestrialWorldParameters::TerrestrialWorldParameters(Json const& store) : Visi
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerrestrialWorldParameters &TerrestrialWorldParameters::operator=(TerrestrialWorldParameters const& terrestrialWorldParameters) {
|
TerrestrialWorldParameters &TerrestrialWorldParameters::operator=(TerrestrialWorldParameters const& terrestrialWorldParameters) {
|
||||||
*this = terrestrialWorldParameters;
|
this->primaryBiome = terrestrialWorldParameters.primaryBiome;
|
||||||
|
this->primarySurfaceLiquid = terrestrialWorldParameters.primarySurfaceLiquid;
|
||||||
|
this->sizeName = terrestrialWorldParameters.sizeName;
|
||||||
|
this->hueShift = terrestrialWorldParameters.hueShift;
|
||||||
|
|
||||||
|
this->skyColoring = terrestrialWorldParameters.skyColoring;
|
||||||
|
this->dayLength = terrestrialWorldParameters.dayLength;
|
||||||
|
|
||||||
|
this->blockNoiseConfig = terrestrialWorldParameters.blockNoiseConfig;
|
||||||
|
this->blendNoiseConfig = terrestrialWorldParameters.blendNoiseConfig;
|
||||||
|
this->blendSize = terrestrialWorldParameters.blendSize;
|
||||||
|
|
||||||
|
this->spaceLayer = terrestrialWorldParameters.spaceLayer;
|
||||||
|
this->atmosphereLayer = terrestrialWorldParameters.atmosphereLayer;
|
||||||
|
this->surfaceLayer = terrestrialWorldParameters.surfaceLayer;
|
||||||
|
this->subsurfaceLayer = terrestrialWorldParameters.subsurfaceLayer;
|
||||||
|
this->undergroundLayers = terrestrialWorldParameters.undergroundLayers;
|
||||||
|
this->coreLayer = terrestrialWorldParameters.coreLayer;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ String LuaBindings::formatLua(String const& string, List<LuaValue> const& args)
|
|||||||
else if (*next == 's')
|
else if (*next == 's')
|
||||||
result += toString(popArg());
|
result += toString(popArg());
|
||||||
else
|
else
|
||||||
throw StarException::format("Improper lua log format specifier %%%c", *next);
|
throw StarException::format("Improper lua log format specifier {}", (char)*next);
|
||||||
++next;
|
++next;
|
||||||
stringIt = next;
|
stringIt = next;
|
||||||
} else {
|
} else {
|
||||||
|
@ -175,7 +175,7 @@ namespace LuaBindings {
|
|||||||
} else if (*order == "random") {
|
} else if (*order == "random") {
|
||||||
Random::shuffle(entities);
|
Random::shuffle(entities);
|
||||||
} else {
|
} else {
|
||||||
throw StarException(strf("Unsupported query order %s", *order));
|
throw StarException(strf("Unsupported query order %s", order->ptr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ String Widget::toStringImpl(int indentLevel) const {
|
|||||||
leader,
|
leader,
|
||||||
m_name,
|
m_name,
|
||||||
leader,
|
leader,
|
||||||
this,
|
(void*)this,
|
||||||
leader,
|
leader,
|
||||||
m_visible ? "true" : "false",
|
m_visible ? "true" : "false",
|
||||||
leader,
|
leader,
|
||||||
|
@ -175,4 +175,6 @@ shared_ptr<WidgetType> Widget::findChild(String const& name) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> struct fmt::formatter<Star::Widget> : ostream_formatter {};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user