Merge pull request #50 from seleznevae/issue-49
Fix incorrect behaviour in case of using standard iostream manipulators with fort::table
This commit is contained in:
commit
ccb892f77d
@ -1,5 +1,9 @@
|
|||||||
## v0.4.1
|
## v0.4.1
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Fix incorrect behaviour in case of using standard iostream manipulators with fort::table.
|
||||||
|
|
||||||
### Internal
|
### Internal
|
||||||
|
|
||||||
- Add alias `libfort::fort` for `fort` target that can be used via `add_subdirectory` in cmake.
|
- Add alias `libfort::fort` for `fort` target that can be used via `add_subdirectory` in cmake.
|
||||||
|
40
lib/fort.hpp
40
lib/fort.hpp
@ -34,9 +34,11 @@ SOFTWARE.
|
|||||||
#ifndef LIBFORT_HPP
|
#ifndef LIBFORT_HPP
|
||||||
#define LIBFORT_HPP
|
#define LIBFORT_HPP
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "fort.h"
|
#include "fort.h"
|
||||||
|
|
||||||
@ -150,6 +152,39 @@ const table_manipulator endr(1);
|
|||||||
*/
|
*/
|
||||||
const table_manipulator separator(2);
|
const table_manipulator separator(2);
|
||||||
|
|
||||||
|
// Utility functions for internal library usage.
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_stream_manipulator_impl() noexcept
|
||||||
|
{
|
||||||
|
using Tdec = typename std::decay<T>::type;
|
||||||
|
// Manipulators for integral types
|
||||||
|
return std::is_same<Tdec, typename std::decay<decltype(std::dec)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::hex)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::oct)>::type>::value
|
||||||
|
// Floating-point manipulators
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::fixed)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::scientific)>::type>::value
|
||||||
|
// Misc
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setbase(0))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setfill('\0'))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setprecision(0))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setw(0))>::type>::value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function that is used internally by the library to check if argument
|
||||||
|
* passed to operator<< is a manipulator. In case default behaviour is not
|
||||||
|
* enough write custom specialization of this function.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_stream_manipulator() noexcept
|
||||||
|
{
|
||||||
|
return detail::is_stream_manipulator_impl<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property owner.
|
* Property owner.
|
||||||
*
|
*
|
||||||
@ -534,8 +569,9 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
table &operator<<(const T &arg)
|
table &operator<<(const T &arg)
|
||||||
{
|
{
|
||||||
|
constexpr bool is_manip = fort::is_stream_manipulator<typename std::decay<T>::type>();
|
||||||
stream_ << arg;
|
stream_ << arg;
|
||||||
if (stream_.tellp() >= 0) {
|
if (stream_.tellp() >= 0 && !is_manip) {
|
||||||
#ifdef FT_HAVE_UTF8
|
#ifdef FT_HAVE_UTF8
|
||||||
if (TT == table_type::character) {
|
if (TT == table_type::character) {
|
||||||
ft_nwrite(table_, 1, stream_.str().c_str());
|
ft_nwrite(table_, 1, stream_.str().c_str());
|
||||||
|
40
src/fort.hpp
40
src/fort.hpp
@ -34,9 +34,11 @@ SOFTWARE.
|
|||||||
#ifndef LIBFORT_HPP
|
#ifndef LIBFORT_HPP
|
||||||
#define LIBFORT_HPP
|
#define LIBFORT_HPP
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "fort.h"
|
#include "fort.h"
|
||||||
|
|
||||||
@ -150,6 +152,39 @@ const table_manipulator endr(1);
|
|||||||
*/
|
*/
|
||||||
const table_manipulator separator(2);
|
const table_manipulator separator(2);
|
||||||
|
|
||||||
|
// Utility functions for internal library usage.
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_stream_manipulator_impl() noexcept
|
||||||
|
{
|
||||||
|
using Tdec = typename std::decay<T>::type;
|
||||||
|
// Manipulators for integral types
|
||||||
|
return std::is_same<Tdec, typename std::decay<decltype(std::dec)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::hex)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::oct)>::type>::value
|
||||||
|
// Floating-point manipulators
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::fixed)>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::scientific)>::type>::value
|
||||||
|
// Misc
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setbase(0))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setfill('\0'))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setprecision(0))>::type>::value
|
||||||
|
|| std::is_same<Tdec, typename std::decay<decltype(std::setw(0))>::type>::value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function that is used internally by the library to check if argument
|
||||||
|
* passed to operator<< is a manipulator. In case default behaviour is not
|
||||||
|
* enough write custom specialization of this function.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_stream_manipulator() noexcept
|
||||||
|
{
|
||||||
|
return detail::is_stream_manipulator_impl<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property owner.
|
* Property owner.
|
||||||
*
|
*
|
||||||
@ -534,8 +569,9 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
table &operator<<(const T &arg)
|
table &operator<<(const T &arg)
|
||||||
{
|
{
|
||||||
|
constexpr bool is_manip = fort::is_stream_manipulator<typename std::decay<T>::type>();
|
||||||
stream_ << arg;
|
stream_ << arg;
|
||||||
if (stream_.tellp() >= 0) {
|
if (stream_.tellp() >= 0 && !is_manip) {
|
||||||
#ifdef FT_HAVE_UTF8
|
#ifdef FT_HAVE_UTF8
|
||||||
if (TT == table_type::character) {
|
if (TT == table_type::character) {
|
||||||
ft_nwrite(table_, 1, stream_.str().c_str());
|
ft_nwrite(table_, 1, stream_.str().c_str());
|
||||||
|
@ -97,6 +97,25 @@ void test_cpp_bug_fixes(void)
|
|||||||
"+------+------+--------------------------------+\n";
|
"+------+------+--------------------------------+\n";
|
||||||
assert_string_equal(table_str, table_str_etalon);
|
assert_string_equal(table_str, table_str_etalon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCENARIO("Issue 49 - https://github.com/seleznevae/libfort/issues/49") {
|
||||||
|
fort::char_table table;
|
||||||
|
table << std::setprecision(5) << 3.14 << std::hex << 256 << fort::endr
|
||||||
|
<< std::fixed << std::setprecision(2) << 11.1234567;
|
||||||
|
std::string table_str = table.to_string();
|
||||||
|
std::string table_str_etalon =
|
||||||
|
"+-------+-----+\n"
|
||||||
|
"| | |\n"
|
||||||
|
"| 3.14 | 100 |\n"
|
||||||
|
"| | |\n"
|
||||||
|
"+-------+-----+\n"
|
||||||
|
"| | |\n"
|
||||||
|
"| 11.12 | |\n"
|
||||||
|
"| | |\n"
|
||||||
|
"+-------+-----+\n";
|
||||||
|
assert_string_equal(table_str, table_str_etalon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_cpp_table_basic(void)
|
void test_cpp_table_basic(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user