#ifndef SPROUT_IO_HPP #define SPROUT_IO_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include HDR_ALGORITHM_MIN_MAX_SSCRISK_CEL_OR_SPROUT namespace sprout { namespace io { namespace flags { // // fmtflags // enum fmtflags { boolalpha = 1L << 0, showbase = 1L << 1, showpoint = 1L << 2, showpos = 1L << 3, uppercase = 1L << 4, skipws = 1L << 5, right = 1L << 6, left = 1L << 7, internal = 1L << 8, dec = 1L << 9, hex = 1L << 10, oct = 1L << 11, fixed = 1L << 12, scientific = 1L << 13, adjustfield = right | left | internal, basefield = dec | hex | oct, floatfield = fixed | scientific, booleanfield = boolalpha | showbase | showpoint | showpos | uppercase | skipws, default_flags = right | dec | fixed, precision_ = 1L << 14, width_ = 1L << 15, fill_ = 1L << 16, modified_shift_ = 17, }; // // boolean_flag // template struct boolean_flag : public std::integral_constant { private: bool flag_; public: boolean_flag() = default; boolean_flag(boolean_flag const&) = default; SPROUT_CONSTEXPR boolean_flag(bool flag) : flag_(flag) {} SPROUT_CONSTEXPR boolean_flag operator()(bool flag) const { return boolean_flag(flag); } SPROUT_CONSTEXPR operator bool() const { return flag_; } SPROUT_CONSTEXPR bool operator!() const { return !flag_; } }; // // field_flag // template struct field_flag : public std::integral_constant { public: SPROUT_STATIC_CONSTEXPR sprout::io::flags::fmtflags mask = Mask; public: field_flag() = default; field_flag(field_flag const&) = default; }; template SPROUT_CONSTEXPR_OR_CONST sprout::io::flags::fmtflags sprout::io::flags::field_flag::mask; // // precision_t // struct precision_t { public: typedef std::streamsize type; public: type value; public: SPROUT_CONSTEXPR precision_t(type value) : value(value) {} SPROUT_CONSTEXPR operator type() const { return value; } }; // // width_t // struct width_t { public: typedef std::streamsize type; public: type value; public: SPROUT_CONSTEXPR width_t(type value) : value(value) {} SPROUT_CONSTEXPR operator type() const { return value; } }; // // fill_t // struct fill_t { public: typedef char type; public: type value; public: SPROUT_CONSTEXPR fill_t(type value) : value(value) {} SPROUT_CONSTEXPR operator type() const { return value; } }; } // namespace flags SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag boolalpha = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag showbase = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag showpoint = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag showpos = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag uppercase = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::boolean_flag skipws = true; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag right = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag left = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag internal = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag dec = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag hex = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag oct = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag fixed = {}; SPROUT_STATIC_CONSTEXPR sprout::io::flags::field_flag scientific = {}; // // precision // width // fill // inline SPROUT_CONSTEXPR sprout::io::flags::precision_t precision(sprout::io::flags::precision_t::type value) { return sprout::io::flags::precision_t(value); } inline SPROUT_CONSTEXPR sprout::io::flags::width_t width(sprout::io::flags::width_t::type value) { return sprout::io::flags::width_t(value); } inline SPROUT_CONSTEXPR sprout::io::flags::fill_t fill(sprout::io::flags::fill_t::type value) { return sprout::io::flags::fill_t(value); } // // format_settings // class format_settings { private: sprout::io::flags::fmtflags flags_; sprout::io::flags::precision_t precision_; sprout::io::flags::width_t width_; sprout::io::flags::fill_t fill_; private: SPROUT_CONSTEXPR format_settings(format_settings const& other, sprout::io::flags::fmtflags flags) : flags_(flags) , precision_(other.precision_) , width_(other.width_) , fill_(other.fill_) {} SPROUT_CONSTEXPR format_settings(format_settings const& other, sprout::io::flags::precision_t precision) : flags_(static_cast(other.flags_ | sprout::io::flags::precision_)) , precision_(precision) , width_(other.width_) , fill_(other.fill_) {} SPROUT_CONSTEXPR format_settings(format_settings const& other, sprout::io::flags::width_t width) : flags_(static_cast(other.flags_ | sprout::io::flags::width_)) , precision_(other.precision_) , width_(width) , fill_(other.fill_) {} SPROUT_CONSTEXPR format_settings(format_settings const& other, sprout::io::flags::fill_t fill) : flags_(static_cast(other.flags_ | sprout::io::flags::fill_)) , precision_(other.precision_) , width_(other.width_) , fill_(fill) {} SPROUT_CONSTEXPR format_settings( sprout::io::flags::fmtflags flags, sprout::io::flags::precision_t precision, sprout::io::flags::width_t width, sprout::io::flags::fill_t fill ) : flags_(flags) , precision_(precision) , width_(width) , fill_(fill) {} public: SPROUT_CONSTEXPR format_settings() : flags_(sprout::io::flags::default_flags) , precision_(6) , width_(0) , fill_(' ') {} format_settings(format_settings const&) = default; explicit SPROUT_CONSTEXPR format_settings(sprout::io::flags::fmtflags flags) : flags_(flags) , precision_(6) , width_(0) , fill_(' ') {} explicit SPROUT_CONSTEXPR format_settings(sprout::io::flags::precision_t precision) : flags_(sprout::io::flags::default_flags) , precision_(precision) , width_(0) , fill_(' ') {} explicit SPROUT_CONSTEXPR format_settings(sprout::io::flags::width_t width) : flags_(sprout::io::flags::default_flags) , precision_(6) , width_(width) , fill_(' ') {} explicit SPROUT_CONSTEXPR format_settings(sprout::io::flags::fill_t fill) : flags_(sprout::io::flags::default_flags) , precision_(6) , width_(0) , fill_(fill) {} SPROUT_CONSTEXPR sprout::io::flags::fmtflags flags() const { return flags_; } template SPROUT_CONSTEXPR format_settings flags(sprout::io::flags::boolean_flag flag) const { return format_settings( *this, static_cast( (flag ? flags_ | Flag : flags_ & ~Flag) | (Flag << sprout::io::flags::modified_shift_) ) ); } template SPROUT_CONSTEXPR format_settings flags(sprout::io::flags::field_flag flag) const { return format_settings( *this, static_cast( (flags_ & ~Mask) | (Flag & Mask) | (Mask << sprout::io::flags::modified_shift_) ) ); } SPROUT_CONSTEXPR sprout::io::flags::precision_t::type precision() const { return precision_; } SPROUT_CONSTEXPR format_settings precision(sprout::io::flags::precision_t precision) const { return format_settings(*this, precision); } SPROUT_CONSTEXPR sprout::io::flags::width_t::type width() const { return width_; } SPROUT_CONSTEXPR format_settings width(sprout::io::flags::width_t width) const { return format_settings(*this, width); } SPROUT_CONSTEXPR sprout::io::flags::fill_t::type fill() const { return fill_; } SPROUT_CONSTEXPR format_settings fill(sprout::io::flags::fill_t fill) const { return format_settings(*this, fill); } SPROUT_CONSTEXPR format_settings combine(format_settings const& base) const { return format_settings( static_cast( (base.flags_ & ~(flags_ >> sprout::io::flags::modified_shift_)) | flags_ ), flags_ & sprout::io::flags::precision_ ? precision_ : base.precision_, flags_ & sprout::io::flags::width_ ? width_ : base.width_, flags_ & sprout::io::flags::fill_ ? fill_ : base.fill_ ); } }; // // format_holder // template class format_holder { private: sprout::value_holder holder_; sprout::io::format_settings settings_; public: format_holder() = default; format_holder(format_holder const&) = default; explicit SPROUT_CONSTEXPR format_holder(T const& value) : holder_(value) , settings_() {} SPROUT_CONSTEXPR format_holder( T const& value, sprout::io::format_settings const& settings ) : holder_(value) , settings_(settings) {} SPROUT_CONSTEXPR format_holder( format_holder const& holder, sprout::io::format_settings const& settings ) : holder_(holder) , settings_(settings) {} SPROUT_CONSTEXPR T const& value() const { return holder_; } SPROUT_CONSTEXPR sprout::io::format_settings const& settings() const { return settings_; } SPROUT_CONSTEXPR format_holder settings(sprout::io::format_settings const& settings) const { return format_holder(holder_, settings); } }; namespace flags { template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(T const& value, sprout::io::flags::boolean_flag flag) { return sprout::io::format_holder(value, sprout::io::format_settings().flags(flag)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(T const& value, sprout::io::flags::field_flag flag) { return sprout::io::format_holder(value, sprout::io::format_settings().flags(flag)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(T const& value, sprout::io::flags::precision_t precision) { return sprout::io::format_holder(value, sprout::io::format_settings(precision)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(T const& value, sprout::io::flags::width_t width) { return sprout::io::format_holder(value, sprout::io::format_settings(width)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(T const& value, sprout::io::flags::fill_t fill) { return sprout::io::format_holder(value, sprout::io::format_settings(fill)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(sprout::io::format_holder const& holder, sprout::io::flags::boolean_flag flag) { return holder.settings(holder.settings().flags(flag)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(sprout::io::format_holder const& holder, sprout::io::flags::field_flag flag) { return holder.settings(holder.settings().flags(flag)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(sprout::io::format_holder const& holder, sprout::io::flags::precision_t precision) { return holder.settings(holder.settings().precision(precision)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(sprout::io::format_holder const& holder, sprout::io::flags::width_t width) { return holder.settings(holder.settings().width(width)); } template inline SPROUT_CONSTEXPR sprout::io::format_holder operator|(sprout::io::format_holder const& holder, sprout::io::flags::fill_t fill) { return holder.settings(holder.settings().fill(fill)); } } // namespace flags template inline SPROUT_CONSTEXPR sprout::basic_string output(Expression const& expr); // // nil_expression // class nil_expression {}; // // root_expression // class root_expression { private: sprout::io::format_settings settings_; public: SPROUT_CONSTEXPR root_expression() : settings_() {} root_expression(root_expression const&) = default; explicit SPROUT_CONSTEXPR root_expression(sprout::io::format_settings const& settings) : settings_(settings) {} SPROUT_CONSTEXPR sprout::io::format_settings const& settings() const { return settings_; } }; // // leaf_expression // template class leaf_expression { private: sprout::value_holder value_; public: SPROUT_CONSTEXPR leaf_expression() : value_() {} leaf_expression(leaf_expression const&) = default; explicit SPROUT_CONSTEXPR leaf_expression(T const& value) : value_(value) {} SPROUT_CONSTEXPR T const& value() const { return value_; } }; // // format_expression // template class format_expression { private: typedef typename std::conditional< std::is_same::value, Left, Left const& >::type left_held_type; typedef typename std::conditional< std::is_same::value, Right, Right const& >::type right_held_type; private: sprout::value_holder left_; sprout::value_holder right_; public: SPROUT_CONSTEXPR format_expression() : left_() , right_() {} format_expression(format_expression const&) = default; explicit SPROUT_CONSTEXPR format_expression(Left const& left) : left_(left) {} explicit SPROUT_CONSTEXPR format_expression(sprout::value_holder left) : left_(left) {} SPROUT_CONSTEXPR format_expression( Left const& left, Right const& right ) : left_(left) , right_(right) {} SPROUT_CONSTEXPR format_expression( sprout::value_holder left, sprout::value_holder right ) : left_(left) , right_(right) {} SPROUT_CONSTEXPR Left const& left() const { return left_; } SPROUT_CONSTEXPR Right const& right() const { return right_; } SPROUT_CONSTEXPR sprout::io::format_settings const& settings() const { return left().settings(); } template SPROUT_CONSTEXPR sprout::basic_string output() const { return sprout::io::output(*this); } template SPROUT_CONSTEXPR operator sprout::basic_string() const { return sprout::io::output(*this); } }; // // root_t // typedef sprout::io::format_expression< sprout::io::root_expression, sprout::io::nil_expression > root_t; // // root // namespace { SPROUT_STATIC_CONSTEXPR sprout::io::root_t root = {}; } // anonymous-namespace template inline SPROUT_CONSTEXPR auto operator<<(sprout::io::format_expression const& lhs, sprout::io::format_holder const& rhs) -> sprout::io::format_expression< sprout::io::format_expression, decltype(std::declval() << rhs.value()) > { typedef decltype(sprout::io::root << rhs.value()) type; return sprout::io::format_expression, type>( lhs, sprout::io::root_t(sprout::io::root_expression(rhs.settings().combine(lhs.settings()))) << rhs.value() ); } template inline SPROUT_CONSTEXPR sprout::io::format_expression< sprout::io::format_expression, sprout::io::leaf_expression > operator<<(sprout::io::format_expression const& lhs, T const& rhs) { return sprout::io::format_expression< sprout::io::format_expression, sprout::io::leaf_expression >(lhs, sprout::io::leaf_expression(rhs)); } // // leaf_count // namespace detail { template struct leaf_count; template<> struct leaf_count : public std::integral_constant {}; template struct leaf_count > : public std::integral_constant {}; template struct leaf_count > : public std::integral_constant< std::size_t, sprout::io::detail::leaf_count::value + sprout::io::detail::leaf_count::value > {}; } // namespace detail template struct leaf_count : public sprout::io::detail::leaf_count {}; template struct leaf_count : public sprout::io::leaf_count {}; template struct leaf_count : public sprout::io::leaf_count {}; // // leaf_at // namespace detail { template struct leaf_at; template struct leaf_at > { public: typedef T type; }; template struct leaf_at > : public std::conditional< I < sprout::io::leaf_count::value, sprout::io::detail::leaf_at, sprout::io::detail::leaf_at::value, Right> >::type {}; } // namespace detail template struct leaf_at : public sprout::io::detail::leaf_at {}; template struct leaf_at : public sprout::io::leaf_at {}; template struct leaf_at : public sprout::io::leaf_at {}; // // get_leaf // namespace detail { template< std::size_t I, typename Left, typename Right, typename sprout::enabler_if<(I >= sprout::io::leaf_count::value)>::type = sprout::enabler > inline SPROUT_CONSTEXPR sprout::io::format_holder< typename sprout::io::leaf_at >::type > get_leaf(sprout::io::format_expression const& expr); template< std::size_t I, typename Left, typename T, typename sprout::enabler_if<(I == sprout::io::leaf_count::value)>::type = sprout::enabler > inline SPROUT_CONSTEXPR sprout::io::format_holder< typename sprout::io::leaf_at > >::type > get_leaf(sprout::io::format_expression > const& expr) { return sprout::io::format_holder< typename sprout::io::leaf_at > >::type >(expr.right().value(), expr.settings()); } template< std::size_t I, typename Left, typename Right, typename sprout::enabler_if<(I < sprout::io::leaf_count::value)>::type = sprout::enabler > inline SPROUT_CONSTEXPR sprout::io::format_holder< typename sprout::io::leaf_at >::type > get_leaf(sprout::io::format_expression const& expr) { return sprout::io::detail::get_leaf(expr.left()); } template< std::size_t I, typename Left, typename Right, typename sprout::enabler_if<(I >= sprout::io::leaf_count::value)>::type > inline SPROUT_CONSTEXPR sprout::io::format_holder< typename sprout::io::leaf_at >::type > get_leaf(sprout::io::format_expression const& expr) { return sprout::io::detail::get_leaf::value>(expr.right()); } } // namespace detail template inline SPROUT_CONSTEXPR sprout::io::format_holder::type> get_leaf(Expression const& expr) { return sprout::io::detail::get_leaf(expr); } // // eval // template< typename Elem, std::size_t N, typename T, typename sprout::enabler_if< std::is_integral::value && !sprout::is_char_type::value >::type = sprout::enabler > inline SPROUT_CONSTEXPR auto eval(sprout::io::format_holder const& holder) -> decltype(sprout::int_to_string(holder.value())) { return sprout::int_to_string(holder.value()); } template< typename Elem, std::size_t N, typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR auto eval(sprout::io::format_holder const& holder) -> decltype(sprout::float_to_string(holder.value())) { return sprout::float_to_string(holder.value()); } template< typename Elem, std::size_t N, typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR auto eval(sprout::io::format_holder const& holder) -> decltype(sprout::basic_string{{static_cast(holder.value())}, 1}) { return sprout::basic_string{{static_cast(holder.value())}, 1}; } template< typename Elem, std::size_t N, typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR auto eval(sprout::io::format_holder const& holder) -> decltype(sprout::to_string(holder.value())) { return sprout::to_string(holder.value()); } template< typename Elem, std::size_t N, typename T, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR auto eval(sprout::io::format_holder const& holder) -> decltype(holder.value()) { return holder.value(); } namespace detail { template inline SPROUT_CONSTEXPR Elem get_param(Iterator found, sprout::array const& sizes, std::size_t idx, Args const&... args) { return found == sizes.end() ? static_cast('\0') : sprout::detail::param_seq_at( found - sizes.begin(), idx - (found != sizes.begin() ? found[-1] : 0), args... ) ; } } // namespace detail namespace detail { template inline SPROUT_CONSTEXPR sprout::basic_string output_impl_1(sprout::index_tuple, sprout::array const& sizes, Args const&... args) { return sprout::basic_string{ { sprout::io::detail::get_param( sprout::range::lower_bound(sizes, static_cast(Indexes + 1)), sizes, Indexes, args... )... }, NS_SSCRISK_CEL_OR_SPROUT::min(sizes.back(), N) }; } template inline SPROUT_CONSTEXPR sprout::basic_string output_impl(Args const&... args) { return sprout::io::detail::output_impl_1( sprout::index_range<0, N>::make(), sprout::range::partial_sum( sprout::array{{args.size()...}}, sprout::pit >() ), args... ); } template inline SPROUT_CONSTEXPR sprout::basic_string output(Expression const& expr, sprout::index_tuple) { return sprout::io::detail::output_impl( sprout::io::eval(sprout::io::get_leaf(expr))... ); } } // namespace detail // // output // template inline SPROUT_CONSTEXPR sprout::basic_string output(Expression const& expr) { return sprout::io::detail::output( expr, sprout::index_range<0, sprout::io::leaf_count::value>::make() ); } } // namespace io } // namespace sprout #endif // #ifndef SPROUT_IO_HPP