Skip to content

Commit

Permalink
Update implementation of print
Browse files Browse the repository at this point in the history
  • Loading branch information
HenryAWE committed May 28, 2024
1 parent 4a8cf55 commit 108b912
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 275 deletions.
2 changes: 2 additions & 0 deletions example/info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ int main()
println("Papilio Charontis version {0[0]}.{0[1]}.{0[2]}", get_version());
println();

println("Is terminal: {}", os::is_terminal(stdout));

println("Library and compiler information:");
println("PAPILIO_CPLUSPLUS = {:d}L", PAPILIO_CPLUSPLUS);

Expand Down
6 changes: 4 additions & 2 deletions include/papilio/color.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ PAPILIO_EXPORT class text_style
}

template <typename Iterator>
static Iterator reset(Iterator it)
Iterator reset(Iterator it) const
{
constexpr char esc[] = "\033[0m";
return std::copy_n(esc, 4, it);
if(has_style() || has_foreground())
it = std::copy_n(esc, 4, it);
return it;
}

private:
Expand Down
28 changes: 28 additions & 0 deletions include/papilio/os/os.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef PAPILIO_OS_OS_HPP
#define PAPILIO_OS_OS_HPP

#pragma once

#include <papilio/detail/prefix.hpp>
#include <string_view>
#include <system_error>
#include <cstdio>

namespace papilio::os
{
bool is_terminal(std::FILE* file);

void output_conv(
std::FILE* file,
std::string_view out
);

void output_nonconv(
std::FILE* file,
std::string_view out
);
} // namespace papilio::os

#include <papilio/detail/suffix.hpp>

#endif
220 changes: 33 additions & 187 deletions include/papilio/print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

#pragma once

#include <cstdio> // FILE*
#include <iostream>
#include <iterator>
#include "macros.hpp"
#include "os/os.hpp"
#include "format.hpp"
#include "color.hpp"
#include "detail/prefix.hpp"
Expand All @@ -15,139 +14,14 @@ namespace papilio
{
namespace detail
{
// output iterator for C FILE*
class fp_iterator
{
public:
using iterator_category = std::output_iterator_tag;
using value_type = char;
using difference_type = std::ptrdiff_t;

fp_iterator() = delete;
fp_iterator(const fp_iterator&) noexcept = default;

fp_iterator(std::FILE* fp) noexcept
: m_fp(fp) {}

fp_iterator& operator=(const fp_iterator&) noexcept = default;

fp_iterator& operator=(char ch)
{
write(ch);
return *this;
}

fp_iterator& operator*() noexcept
{
return *this;
}

fp_iterator& operator++() noexcept
{
return *this;
}

fp_iterator operator++(int) noexcept
{
return *this;
}

std::FILE* get() const noexcept
{
return m_fp;
}

private:
std::FILE* m_fp;

void write(char ch);
};

class fp_iterator_conv_base
{
public:
fp_iterator_conv_base() noexcept = default;
fp_iterator_conv_base(const fp_iterator_conv_base&) noexcept = default;

fp_iterator_conv_base& operator=(const fp_iterator_conv_base&) noexcept = default;

#ifdef PAPILIO_PLATFORM_WINDOWS

protected:
fp_iterator_conv_base(unsigned int win_cp) noexcept
: m_win_cp(win_cp) {}

unsigned int get_cp() const noexcept
{
return m_win_cp;
}

private:
unsigned int m_win_cp = 0; // 0 == CP_ACP
#else

protected:
fp_iterator_conv_base([[maybe_unused]] unsigned int win_cp) noexcept {}

unsigned int get_cp() const noexcept = delete;
#endif
};

class fp_iterator_conv : public fp_iterator_conv_base
{
public:
using iterator_category = std::output_iterator_tag;
using value_type = char;
using difference_type = std::ptrdiff_t;

fp_iterator_conv() = delete;
fp_iterator_conv(const fp_iterator_conv&) noexcept = default;

fp_iterator_conv(std::FILE* fp, unsigned int win_cp = 0) noexcept
: fp_iterator_conv_base(win_cp), m_underlying(fp) {}

fp_iterator_conv& operator=(const fp_iterator_conv&) noexcept = default;

fp_iterator_conv& operator=(char ch)
{
write(ch);
return *this;
}

fp_iterator_conv& operator*() noexcept
{
return *this;
}

fp_iterator_conv& operator++() noexcept
{
return *this;
}

fp_iterator_conv operator++(int) noexcept
{
return *this;
}

private:
char8_t m_buf[4] = {u8'\0', u8'\0', u8'\0', u8'\0'};
std::uint8_t m_byte_len = 0;
std::uint8_t m_byte_idx = 0;
fp_iterator m_underlying;

void write(char ch);
};

unsigned int get_output_cp_win() noexcept;

inline auto create_iter(std::FILE* file) noexcept
{
#ifdef PAPILIO_PLATFORM_WINDOWS
return fp_iterator_conv(file, get_output_cp_win());
#else
return fp_iterator(file);
#endif
}
void vprint_impl(
std::FILE* file,
std::string_view fmt,
format_args_ref args,
bool conv_unicode,
bool newline,
text_style st = text_style()
);
} // namespace detail

PAPILIO_EXPORT void println(std::FILE* file);
Expand All @@ -156,91 +30,63 @@ PAPILIO_EXPORT void println();
PAPILIO_EXPORT template <typename... Args>
void print(std::FILE* file, format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator;
using context_type = basic_format_context<iter_t>;
PAPILIO_NS vformat_to(
iter_t(file),
detail::vprint_impl(
file,
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
PAPILIO_NS make_format_args(std::forward<Args>(args)...),
os::is_terminal(file),
false
);
}

PAPILIO_EXPORT template <typename... Args>
void print(format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator_conv;
using context_type = basic_format_context<iter_t>;
PAPILIO_NS vformat_to(
iter_t(stdout, detail::get_output_cp_win()),
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
);
PAPILIO_NS print(stdout, fmt, std::forward<Args>(args)...);
}

PAPILIO_EXPORT template <typename... Args>
void print(text_style st, format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator_conv;
using context_type = basic_format_context<iter_t>;

auto it = iter_t(stdout, detail::get_output_cp_win());

it = st.set(it);

it = PAPILIO_NS vformat_to(
it,
detail::vprint_impl(
stdout,
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
PAPILIO_NS make_format_args(std::forward<Args>(args)...),
os::is_terminal(stdout),
false,
st
);

st.reset(it);
}

PAPILIO_EXPORT template <typename... Args>
void println(std::FILE* file, format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator;
using context_type = basic_format_context<iter_t>;
auto it = PAPILIO_NS vformat_to(
iter_t(file),
detail::vprint_impl(
file,
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
PAPILIO_NS make_format_args(std::forward<Args>(args)...),
os::is_terminal(file),
true
);
*it = '\n';
}

PAPILIO_EXPORT template <typename... Args>
void println(format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator_conv;
using context_type = basic_format_context<iter_t>;
auto it = vformat_to(
iter_t(stdout, detail::get_output_cp_win()),
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
);
*it = '\n';
PAPILIO_NS println(stdout, fmt, std::forward<Args>(args)...);
}

PAPILIO_EXPORT template <typename... Args>
void println(text_style st, format_string<Args...> fmt, Args&&... args)
{
using iter_t = detail::fp_iterator_conv;
using context_type = basic_format_context<iter_t>;

auto it = iter_t(stdout, detail::get_output_cp_win());

it = st.set(it);

it = PAPILIO_NS vformat_to(
it,
detail::vprint_impl(
stdout,
fmt.get(),
PAPILIO_NS make_format_args<context_type>(std::forward<Args>(args)...)
PAPILIO_NS make_format_args(std::forward<Args>(args)...),
os::is_terminal(stdout),
true,
st
);

it = st.reset(it);

*it = '\n';
}

PAPILIO_EXPORT template <typename... Args>
Expand Down
27 changes: 27 additions & 0 deletions src/os/general.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "os_impl.hpp"
#include <papilio/detail/prefix.hpp>

namespace papilio::os
{
void output_nonconv(
std::FILE* file,
std::string_view out
)
{
using namespace std;

size_t result = fwrite(
out.data(), 1, out.size(), file
);
if(result < out.size())
{
throw std::system_error(
std::make_error_code(std::errc::io_error)
);
}

fflush(file);
}
} // namespace papilio::os

#include <papilio/detail/suffix.hpp>
17 changes: 17 additions & 0 deletions src/os/os_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef PAPILIO_OS_OS_IMPL_HPP
#define PAPILIO_OS_OS_IMPL_HPP

#pragma once

#include <papilio/detail/prefix.hpp>
#include <papilio/os/os.hpp>

#ifdef PAPILIO_PLATFORM_WINDOWS
# define PAPILIO_OS_IMPL_WINAPI 1
#else
# define PAPILIO_OS_IMPL_POSIX 1
#endif

#include <papilio/detail/suffix.hpp>

#endif
Loading

0 comments on commit 108b912

Please sign in to comment.