aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/libcxx/include/__format/format_context.h
blob: 570bf7e90d9f13afe8d8c3461bf51ff6818d4d84 (plain) (blame)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___FORMAT_FORMAT_CONTEXT_H
#define _LIBCPP___FORMAT_FORMAT_CONTEXT_H

#include <__availability>
#include <__config>
#include <__format/format_args.h>
#include <__format/format_fwd.h>
#include <__iterator/back_insert_iterator.h>
#include <__iterator/concepts.h>
#include <concepts>

#ifndef _LIBCPP_HAS_NO_LOCALIZATION
#include <locale>
#include <optional>
#endif

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER > 17

// TODO FMT Remove this once we require compilers with proper C++20 support.
// If the compiler has no concepts support, the format header will be disabled.
// Without concepts support enable_if needs to be used and that too much effort
// to support compilers with partial C++20 support.
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)

template <class _OutIt, class _CharT>
requires output_iterator<_OutIt, const _CharT&>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context;

#ifndef _LIBCPP_HAS_NO_LOCALIZATION
/**
 * Helper to create a basic_format_context.
 *
 * This is needed since the constructor is private.
 */
template <class _OutIt, class _CharT>
_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
__format_context_create(
    _OutIt __out_it,
    basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
    optional<_VSTD::locale>&& __loc = nullopt) {
  return _VSTD::basic_format_context(_VSTD::move(__out_it), __args,
                                     _VSTD::move(__loc));
}
#else
template <class _OutIt, class _CharT>
_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
__format_context_create(
    _OutIt __out_it,
    basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
  return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
}
#endif

// TODO FMT Implement [format.context]/4
// [Note 1: For a given type charT, implementations are encouraged to provide a
// single instantiation of basic_format_context for appending to
// basic_string<charT>, vector<charT>, or any other container with contiguous
// storage by wrapping those in temporary objects with a uniform interface
// (such as a span<charT>) and polymorphic reallocation. - end note]

using format_context = basic_format_context<back_insert_iterator<string>, char>;
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
using wformat_context = basic_format_context<back_insert_iterator<wstring>, wchar_t>;
#endif

template <class _OutIt, class _CharT>
requires output_iterator<_OutIt, const _CharT&>
class
    // clang-format off
    _LIBCPP_TEMPLATE_VIS
    _LIBCPP_AVAILABILITY_FORMAT
    _LIBCPP_PREFERRED_NAME(format_context)
    _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context))
    // clang-format on
    basic_format_context {
public:
  using iterator = _OutIt;
  using char_type = _CharT;
  template <class _Tp>
  using formatter_type = formatter<_Tp, _CharT>;

  basic_format_context(const basic_format_context&) = delete;
  basic_format_context& operator=(const basic_format_context&) = delete;

  _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context>
  arg(size_t __id) const {
    return __args_.get(__id);
  }
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
  _LIBCPP_HIDE_FROM_ABI _VSTD::locale locale() {
    if (!__loc_)
      __loc_ = _VSTD::locale{};
    return *__loc_;
  }
#endif
  _LIBCPP_HIDE_FROM_ABI iterator out() { return __out_it_; }
  _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = __it; }

private:
  iterator __out_it_;
  basic_format_args<basic_format_context> __args_;
#ifndef _LIBCPP_HAS_NO_LOCALIZATION

  // The Standard doesn't specify how the locale is stored.
  // [format.context]/6
  // std::locale locale();
  //   Returns: The locale passed to the formatting function if the latter
  //   takes one, and std::locale() otherwise.
  // This is done by storing the locale of the constructor in this optional. If
  // locale() is called and the optional has no value the value will be created.
  // This allows the implementation to lazily create the locale.
  // TODO FMT Validate whether lazy creation is the best solution.
  optional<_VSTD::locale> __loc_;

  template <class __OutIt, class __CharT>
  friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
  __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>,
                          optional<_VSTD::locale>&&);

  // Note: the Standard doesn't specify the required constructors.
  _LIBCPP_HIDE_FROM_ABI
  explicit basic_format_context(_OutIt __out_it,
                                basic_format_args<basic_format_context> __args,
                                optional<_VSTD::locale>&& __loc)
      : __out_it_(_VSTD::move(__out_it)), __args_(__args),
        __loc_(_VSTD::move(__loc)) {}
#else
  template <class __OutIt, class __CharT>
  friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT>
      __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>);

  _LIBCPP_HIDE_FROM_ABI
  explicit basic_format_context(_OutIt __out_it,
                                basic_format_args<basic_format_context> __args)
      : __out_it_(_VSTD::move(__out_it)), __args_(__args) {}
#endif
};

#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)

#endif //_LIBCPP_STD_VER > 17

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H