/**
This file is a part of rexy's general purpose library
Copyright (C) 2022 rexy712
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 3 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 .
*/
#ifndef REXY_DETAIL_FORMAT_FORMAT_ARGS_HPP
#define REXY_DETAIL_FORMAT_FORMAT_ARGS_HPP
#include //size_t
#include //monostate
#include "storage.hpp" //storage_type
#include "basic_types.hpp" //arg_info
#include "arg_store.hpp"
#include "traits.hpp"
#include "../../string_view.hpp"
namespace rexy::fmt{
//Type erasure of single argument.
//Context is an instantiation of 'basic_format_context'
template
class basic_format_arg
{
public:
using char_type = typename Context::char_type;
public:
//Handles call to formatter for a user defined type
//type erase the user defined values
class handle
{
public:
using format_ptr_t = void(handle::*)(basic_format_parse_context&, Context&)const;
public:
const void* m_data;
format_ptr_t m_format_impl;
public:
template
explicit handle(T&& t);
template
void format_impl(basic_format_parse_context& parse_ctx, Context& format_ctx)const;
void format(basic_format_parse_context& parse_ctx, Context& format_ctx)const;
};
union{
std::monostate none_v = {};
bool bool_v;
char_type char_v;
int int_v;
unsigned int uint_v;
long long long_long_v;
unsigned long long ulong_long_v;
float float_v;
double double_v;
long double long_double_v;
const char_type* char_ptr_v;
basic_string_view string_v;
const void* ptr_v;
handle custom_v;
};
detail::storage_type active_member = detail::storage_type::none_t;
//initialize std::variant equivalent to std::monostate
basic_format_arg(void)noexcept{}
explicit basic_format_arg(bool b)noexcept;
explicit basic_format_arg(char_type b)noexcept;
explicit basic_format_arg(int b)noexcept;
explicit basic_format_arg(unsigned int b)noexcept;
explicit basic_format_arg(long long b)noexcept;
explicit basic_format_arg(unsigned long long b)noexcept;
explicit basic_format_arg(float b)noexcept;
explicit basic_format_arg(double b)noexcept;
explicit basic_format_arg(long double b)noexcept;
explicit basic_format_arg(const char_type* b)noexcept;
explicit basic_format_arg(basic_string_view b)noexcept;
explicit basic_format_arg(const void* b)noexcept;
explicit basic_format_arg(const handle b)noexcept;
detail::storage_type type(void)const;
explicit operator bool(void)const noexcept;
};
//Holds list of arguments, erasing concrete types.
//Context is an instantiation of 'basic_format_context'
template
class basic_format_args
{
public:
using char_type = detail::extract_char_type_from_context_t;
private:
//TODO less pointers
const detail::arg_info* m_info = nullptr;
const unsigned char* m_data = nullptr;
const std::size_t m_num_args = 0;
public:
basic_format_args(void)noexcept = default;
constexpr basic_format_args(const detail::basic_format_arg_store& store)noexcept;
template
basic_format_args(const detail::basic_format_arg_store& store)noexcept;
basic_format_arg get(std::size_t i)const noexcept;
basic_format_arg get(const char_type* first, const char_type* last)const;
std::size_t get_index(const char_type* first, const char_type* last)const;
};
//Visitor for basic_format_arg
template
decltype(auto) visit_format_arg(Fun&& fun, const basic_format_arg& arg);
}
#endif