aboutsummaryrefslogtreecommitdiff
path: root/libs/kstd/kstd/bits/format/vformat.hpp
blob: 829e0ea463327ad1ba8133d380f0849f35f44229 (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
#ifndef KSTD_BITS_FORMAT_VFORMAT_HPP
#define KSTD_BITS_FORMAT_VFORMAT_HPP

// IWYU pragma: private, include <kstd/format.hpp>

#include <kstd/bits/basic_string.hpp>
#include <kstd/bits/format/args.hpp>
#include <kstd/bits/format/output_buffer.hpp>
#include <kstd/bits/format/string.hpp>

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <string_view>
#include <type_traits>

namespace kstd
{

  namespace bits::format
  {
    //! Format a string with the given arguments into the given buffer.
    //!
    //! External implementations of `vprint` may call this function.
    //!
    //! @param buffer The buffer to format into.
    //! @param format The format string to use.
    //! @param args The arguments for the format string.
    auto vformat_to(output_buffer & buffer, std::string_view format, format_args args) -> void;

    struct string_writer : output_buffer
    {
      auto push(std::string_view text) -> void final;
      auto push(char character) -> void final;

      auto release() -> basic_string<char> &&;

    private:
      basic_string<char> m_result{};
    };

    //! A buffer that merely records the size of the output written to it.
    struct size_recorder : output_buffer
    {
      auto push(std::string_view text) -> void final;
      auto push(char character) -> void final;

      [[nodiscard]] auto size() const noexcept -> std::size_t;

    private:
      std::size_t m_size{};
    };

    template<std::output_iterator<char> Output>
    struct iterator_writer : output_buffer
    {
      explicit iterator_writer(Output iterator)
          : m_output{iterator}
      {}

      [[nodiscard]] auto iterator() const -> Output
      {
        return m_output;
      }

      auto push(std::string_view text) -> void override
      {
        m_output = std::ranges::copy(text, m_output).out;
      }

      auto push(char character) -> void override
      {
        *m_output++ = character;
      }

    private:
      Output m_output{};
    };

  }  // namespace bits::format

  //! Format a given string with the provided arguments.
  //!
  //! @param format The format string.
  //! @param args The arguments for the format string.
  //! @return A new string containing the result of the format operation.
  template<typename... ArgumentTypes>
  auto format(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
      -> basic_string<char>
  {
    auto buffer = bits::format::string_writer{};
    bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
    return buffer.release();
  }

  //! Format a given string with the provided arguments.
  //!
  //! @param iterator The iterator to write to.
  //! @param format The format string.
  //! @param args The arguments for the format string.
  //! @return An iterator past the last element written.
  template<std::output_iterator<char> Output, typename... ArgumentTypes>
  auto format_to(Output iterator, format_string<std::type_identity_t<ArgumentTypes>...> format,
                 ArgumentTypes &&... args) -> Output
  {
    auto buffer = bits::format::iterator_writer{iterator};
    bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
    return buffer.iterator();
  }

  //! Determine the number of characters required to format the format string with the given arguments.
  //!
  //! @param format The format string.
  //! @param args The arguments for the format string.
  //! @tparam ArgumentTypes The type of the format string arguments.
  //! @return The number of characters required to format @p format with @p args
  template<typename... ArgumentTypes>
  auto formatted_size(format_string<std::type_identity_t<ArgumentTypes>...> format, ArgumentTypes &&... args)
      -> std::size_t
  {
    auto buffer = bits::format::size_recorder{};
    bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args);
    return buffer.size();
  }

}  // namespace kstd

#endif