Files
clang-p2996/libcxx/include/__format/format_context.h
Mark de Wever 0922ce56f4 [libc++][format] Add __format_arg_store.
This implements the struct `__format_arg_store` and its dependencies:
* the class basic_format_arg,
* the class basic_format_args,
* the class basic_format_context,
* the function make_format_args,
* the function wmake_format_args,
* the function visit_format_arg,
* several Standard required typedefs.

The following parts will be implemented in a later patch:

* the child class `basic_format_arg::handle`,
* the function `basic_format_arg::basic_format_arg(const T* p)`.

The following extension has been implemented:
* the class basic_format_arg supports `__[u]int128_t` on platform where libc++ supports 128 bit integrals.

Implements parts of:
* P0645 Text Formatting

Completes:
* LWG3371 visit_format_arg and make_format_args are not hidden friends
* LWG3542 basic_format_arg mishandles basic_string_view with custom traits

Note https://mordante.github.io/blog/2021/06/05/format.html gives a bit more information about the goals and non-goals of this initial patch series.

Reviewed By: #libc, ldionne, vitaut

Differential Revision: https://reviews.llvm.org/D103357
2021-09-01 19:45:02 +02:00

161 lines
5.5 KiB
C++

// -*- 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/concepts.h>
#include <concepts>
#include <iterator>
#include <string>
#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
template <class _OutIt, class _CharT>
requires output_iterator<_OutIt, const _CharT&>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT 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>
_VSTD::__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>
_VSTD::__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
};
// 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>;
using wformat_context =
basic_format_context<back_insert_iterator<wstring>, wchar_t>;
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
#endif //_LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___FORMAT_FORMAT_CONTEXT_H