brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 1771dd3 Raw
216 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___FORMAT_FORMAT_CONTEXT_H11#define _LIBCPP___FORMAT_FORMAT_CONTEXT_H12 13#include <__concepts/same_as.h>14#include <__config>15#include <__format/buffer.h>16#include <__format/format_arg.h>17#include <__format/format_arg_store.h>18#include <__format/format_args.h>19#include <__format/format_error.h>20#include <__fwd/format.h>21#include <__iterator/back_insert_iterator.h>22#include <__iterator/concepts.h>23#include <__memory/addressof.h>24#include <__utility/move.h>25#include <__variant/monostate.h>26 27#if _LIBCPP_HAS_LOCALIZATION28#  include <__locale>29#  include <optional>30#endif31 32#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)33#  pragma GCC system_header34#endif35 36_LIBCPP_PUSH_MACROS37#include <__undef_macros>38 39_LIBCPP_BEGIN_NAMESPACE_STD40 41#if _LIBCPP_STD_VER >= 2042 43template <class _OutIt, class _CharT>44  requires output_iterator<_OutIt, const _CharT&>45class basic_format_context;46 47#  if _LIBCPP_HAS_LOCALIZATION48/**49 * Helper to create a basic_format_context.50 *51 * This is needed since the constructor is private.52 */53template <class _OutIt, class _CharT>54_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>55__format_context_create(_OutIt __out_it,56                        basic_format_args<basic_format_context<_OutIt, _CharT>> __args,57                        optional<std::locale>&& __loc = nullopt) {58  return std::basic_format_context(std::move(__out_it), __args, std::move(__loc));59}60#  else61template <class _OutIt, class _CharT>62_LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>63__format_context_create(_OutIt __out_it, basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {64  return std::basic_format_context(std::move(__out_it), __args);65}66#  endif67 68using format_context = basic_format_context<back_insert_iterator<__format::__output_buffer<char>>, char>;69#  if _LIBCPP_HAS_WIDE_CHARACTERS70using wformat_context = basic_format_context< back_insert_iterator<__format::__output_buffer<wchar_t>>, wchar_t>;71#  endif72 73template <class _OutIt, class _CharT>74  requires output_iterator<_OutIt, const _CharT&>75class _LIBCPP_PREFERRED_NAME(format_context)76    _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) basic_format_context {77public:78  using iterator  = _OutIt;79  using char_type = _CharT;80  template <class _Tp>81  using formatter_type = formatter<_Tp, _CharT>;82 83  _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept {84    return __args_.get(__id);85  }86#  if _LIBCPP_HAS_LOCALIZATION87  _LIBCPP_HIDE_FROM_ABI std::locale locale() {88    if (!__loc_)89      __loc_ = std::locale{};90    return *__loc_;91  }92#  endif93  _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); }94  _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); }95 96private:97  iterator __out_it_;98  basic_format_args<basic_format_context> __args_;99#  if _LIBCPP_HAS_LOCALIZATION100 101  // The Standard doesn't specify how the locale is stored.102  // [format.context]/6103  // std::locale locale();104  //   Returns: The locale passed to the formatting function if the latter105  //   takes one, and std::locale() otherwise.106  // This is done by storing the locale of the constructor in this optional. If107  // locale() is called and the optional has no value the value will be created.108  // This allows the implementation to lazily create the locale.109  // TODO FMT Validate whether lazy creation is the best solution.110  optional<std::locale> __loc_;111 112  template <class _OtherOutIt, class _OtherCharT>113  friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT> __format_context_create(114      _OtherOutIt, basic_format_args<basic_format_context<_OtherOutIt, _OtherCharT>>, optional<std::locale>&&);115 116  // Note: the Standard doesn't specify the required constructors.117  _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(118      _OutIt __out_it, basic_format_args<basic_format_context> __args, optional<std::locale>&& __loc)119      : __out_it_(std::move(__out_it)), __args_(__args), __loc_(std::move(__loc)) {}120#  else121  template <class _OtherOutIt, class _OtherCharT>122  friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT>123      __format_context_create(_OtherOutIt, basic_format_args<basic_format_context<_OtherOutIt, _OtherCharT>>);124 125  _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(_OutIt __out_it, basic_format_args<basic_format_context> __args)126      : __out_it_(std::move(__out_it)), __args_(__args) {}127#  endif128 129public:130  basic_format_context(const basic_format_context&)            = delete;131  basic_format_context& operator=(const basic_format_context&) = delete;132};133 134// A specialization for __retarget_buffer135//136// See __retarget_buffer for the motivation for this specialization.137//138// This context holds a reference to the instance of the basic_format_context139// that is retargeted. It converts a formatting argument when it is requested140// during formatting. It is expected that the usage of the arguments is rare so141// the lookups are not expected to be used often. An alternative would be to142// convert all elements during construction.143//144// The elements of the retargets context are only used when an underlying145// formatter uses a locale specific formatting or an formatting argument is146// part for the format spec. For example147//   format("{:256:{}}", input, 8);148// Here the width of an element in input is determined dynamically.149// Note when the top-level element has no width the retargeting is not needed.150template <class _CharT>151class basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> {152public:153  using iterator  = typename __format::__retarget_buffer<_CharT>::__iterator;154  using char_type = _CharT;155  template <class _Tp>156  using formatter_type = formatter<_Tp, _CharT>;157 158  template <class _Context>159  _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(iterator __out_it, _Context& __ctx)160      : __out_it_(std::move(__out_it)),161#  if _LIBCPP_HAS_LOCALIZATION162        __loc_([](void* __c) { return static_cast<_Context*>(__c)->locale(); }),163#  endif164        __ctx_(std::addressof(__ctx)),165        __arg_([](void* __c, size_t __id) {166          auto __visitor = [&](auto __arg) -> basic_format_arg<basic_format_context> {167            if constexpr (same_as<decltype(__arg), monostate>)168              return {};169            else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Context>::handle>)170              // At the moment it's not possible for formatting to use a re-targeted handle.171              // TODO FMT add this when support is needed.172              std::__throw_format_error("Re-targeting handle not supported");173            else174              return basic_format_arg<basic_format_context>{175                  __format::__determine_arg_t<basic_format_context, decltype(__arg)>(),176                  __basic_format_arg_value<basic_format_context>(__arg)};177          };178#  if _LIBCPP_STD_VER >= 26179          return static_cast<_Context*>(__c)->arg(__id).visit(std::move(__visitor));180#  else181          _LIBCPP_SUPPRESS_DEPRECATED_PUSH182          return std::visit_format_arg(std::move(__visitor), static_cast<_Context*>(__c)->arg(__id));183          _LIBCPP_SUPPRESS_DEPRECATED_POP184#  endif // _LIBCPP_STD_VER >= 26185        }) {186  }187 188  _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept {189    return __arg_(__ctx_, __id);190  }191#  if _LIBCPP_HAS_LOCALIZATION192  _LIBCPP_HIDE_FROM_ABI std::locale locale() { return __loc_(__ctx_); }193#  endif194  _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); }195  _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); }196 197private:198  iterator __out_it_;199 200#  if _LIBCPP_HAS_LOCALIZATION201  std::locale (*__loc_)(void* __ctx);202#  endif203 204  void* __ctx_;205  basic_format_arg<basic_format_context> (*__arg_)(void* __ctx, size_t __id);206};207 208_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context);209#endif // _LIBCPP_STD_VER >= 20210 211_LIBCPP_END_NAMESPACE_STD212 213_LIBCPP_POP_MACROS214 215#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H216