aboutsummaryrefslogtreecommitdiff
path: root/src/common/Utilities/StringFormat.h
blob: 2016eab0ba3780b754022c2adc4139a0a7350676 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef TRINITYCORE_STRING_FORMAT_H
#define TRINITYCORE_STRING_FORMAT_H

#include "Optional.h"
#include "StringFormatFwd.h"
#include <fmt/core.h>

namespace Trinity
{
    template<typename... Args>
    using FormatString = fmt::format_string<Args...>;

    using FormatStringView = fmt::string_view;

    using FormatArgs = fmt::format_args;

    template<typename... Args>
    constexpr auto MakeFormatArgs(Args&&... args) { return fmt::make_format_args(args...); }

    /// Default TC string format function.
    template<typename... Args>
    inline std::string StringFormat(FormatString<Args...> fmt, Args&&... args)
    {
        try
        {
            return fmt::format(fmt, std::forward<Args>(args)...);
        }
        catch (std::exception const& formatError)
        {
            return fmt::format("An error occurred formatting string \"{}\" : {}", FormatStringView(fmt), formatError.what());
        }
    }

    template<typename OutputIt, typename... Args>
    inline OutputIt StringFormatTo(OutputIt out, FormatString<Args...> fmt, Args&&... args)
    {
        try
        {
            return fmt::format_to(out, fmt, std::forward<Args>(args)...);
        }
        catch (std::exception const& formatError)
        {
            return fmt::format_to(out, "An error occurred formatting string \"{}\" : {}", FormatStringView(fmt), formatError.what());
        }
    }

    inline std::string StringVFormat(FormatStringView fmt, FormatArgs args)
    {
        try
        {
            return fmt::vformat(fmt, args);
        }
        catch (std::exception const& formatError)
        {
            return fmt::format("An error occurred formatting string \"{}\" : {}", fmt, formatError.what());
        }
    }

    template<typename OutputIt>
    inline OutputIt StringVFormatTo(OutputIt out, FormatStringView fmt, FormatArgs args)
    {
        try
        {
            return fmt::vformat_to(out, fmt, args);
        }
        catch (std::exception const& formatError)
        {
            return fmt::format_to(out, "An error occurred formatting string \"{}\" : {}", fmt, formatError.what());
        }
    }

    /// Returns true if the given char pointer is null.
    inline bool IsFormatEmptyOrNull(char const* fmt)
    {
        return fmt == nullptr;
    }

    /// Returns true if the given std::string is empty.
    inline bool IsFormatEmptyOrNull(std::string const& fmt)
    {
        return fmt.empty();
    }

    /// Returns true if the given std::string_view is empty.
    inline constexpr bool IsFormatEmptyOrNull(std::string_view fmt)
    {
        return fmt.empty();
    }

    inline constexpr bool IsFormatEmptyOrNull(fmt::string_view fmt)
    {
        return fmt.size() == 0;
    }
}

template<typename T, typename Char>
struct fmt::formatter<Optional<T>, Char> : formatter<T, Char>
{
    template<typename FormatContext>
    auto format(Optional<T> const& value, FormatContext& ctx) const -> decltype(ctx.out())
    {
        if (value.has_value())
            return formatter<T, Char>::format(*value, ctx);

        return formatter<string_view, Char>().format("(nullopt)", ctx);
    }
};

// allow implicit enum to int conversions for formatting
template <typename E, std::enable_if_t<std::is_enum_v<E>, std::nullptr_t> = nullptr>
auto format_as(E e) { return std::underlying_type_t<E>(e); }

#endif