void print( std::basic_ostream< Ch, Traits > &_stream, fcppt::container::tree::object< Value > const &_tree, unsigned const _indent ) { for( unsigned index = 0; index < _indent; ++index ) _stream << _stream.widen('\t'); _stream << _tree.value() << _stream.widen('\n'); for( auto child : _tree ) fcppt::container::tree::detail::print( _stream, child, _indent + 1u ); }
basic_csv_ostream<Char, Traits>::basic_csv_ostream (std::basic_ostream<Char, Traits> & os, char_type delimiter) : os_(os) , delim_(delimiter) , quote_(os.widen(QUOTE)) , first_(true) {}
basic_csv_ostream<Char, Traits>::basic_csv_ostream (std::basic_ostream<Char, Traits> & os) : os_(os) , delim_(os.widen(COMMA)) , quote_(os.widen(QUOTE)) , first_(true) {}
void escape_char(std::basic_ostream<Char, Traits> &os, Char c, Char delim) { const char escape = '\\'; if(c < 32 || c == 0x7f) { os << escape; switch(c) { case '\0': os << os.widen('0'); break; case '\a': os << os.widen('a'); break; case '\b': os << os.widen('b'); break; case '\f': os << os.widen('f'); break; case '\n': os << os.widen('n'); break; case '\r': os << os.widen('r'); break; case '\t': os << os.widen('t'); break; case '\v': os << os.widen('v'); break; default: os << os.widen('x') << static_cast<unsigned long>(c); } } else if(c == delim || c == escape) { os << escape << c; } else { os << c; } }
inline void fprint(std::basic_ostream<Elem, Traits>& out, const std::basic_string<Elem, Traits>& str, Args&&... arguments) { if(sizeof...(arguments) < 1) { out << str; return; } auto args = std::make_tuple(std::forward<Args>(arguments)...); string::is_digit cmp; auto&& length = str.size(); auto&& original_width = out.width(); std::ios_base::fmtflags original_format = out.flags(); auto&& original_precision = out.precision(); for(decltype(str.size()) i = 0; i < length; ++i) { auto&& c = str[i]; // doesn't start with { so just print it and continue if(c != out.widen('{')) { out << c; continue; } // at this point, the character c points to { // check if we're done printing if(i + 1 > length) { out << c; break; } // check the next characters auto j = i + 1; unsigned index = 0; decltype(out.width()) width = 0; decltype(out.precision()) precision = 0; auto format = original_format; // escaped character if(str[j] == out.widen('{')) { out << str[i]; i = j; continue; } // now we're at a sane point where we can work with the format string // check if the next character is a digit if(cmp(str[j])) { do { // since it is, multiply the index index = (index * 10) + (str[j++] - out.widen('0')); } while(j < length && cmp(str[j])); } else { // since it isn't a digit, it doesn't match our format string throw std::runtime_error("invalid format string specified"); } // check if alignment argument exists if(str[j] == out.widen(',')) { // check if the next character is valid if(j + 1 < length) { // check if the alignment is left or right if(str[j + 1] == out.widen('-')) { format |= out.left; // increment by two to get to the numerical section j += 2; } else { format |= out.right; ++j; } // check if the next character is a digit if(j < length && cmp(str[j])) { do { // since it is, multiply the width width = (width * 10) + (str[j++] - out.widen('0')); } while(j < length && cmp(str[j])); } else { // invalid format string found throw std::runtime_error("invalid format string specified"); } } } // check if format specifier exists if(str[j] == out.widen(':')) { // check if the character is valid if(j + 1 < length) { auto&& specifier = str[j + 1]; switch(specifier) { case 'F': format |= out.fixed; break; case 'O': format = (format & ~out.basefield) | out.oct; break; case 'x': format = (format & ~out.basefield) | out.hex; break; case 'X': format = (format & ~out.basefield) | out.hex | out.uppercase; break; case 'E': format |= out.scientific | out.uppercase; break; case 'e': format |= out.scientific; break; case 'B': format |= out.boolalpha; break; case 'S': format |= out.showpos; break; default: throw std::runtime_error("no such format specifier found"); break; } j += 2; // handle precision specifier if(j < length && cmp(str[j])) { do { precision = (precision * 10) + (str[j++] - out.widen('0')); } while(j < length && cmp(str[j])); } } } // now that we're done processing, handle the results if(str[j] == out.widen('}')) { out.flags(format); out.width(width); out.precision(precision); detail::index_printer(out, index, args); out.width(original_width); out.flags(original_format); out.precision(original_precision); i = j; } } }
inline void fprint(std::basic_ostream<Char, Trait>& out, const Char* str, Args&&... arguments) { // %[parameter][flags][width][.precision]verb // if it's *n$ instead of %n$ then it'll use the specific parameter number // n starts at 1 to sizeof...(Args) // at the moment I'm too lazy to do * at all. auto&& args = std::make_tuple(std::forward<Args>(arguments)...); stream_state<Char, Trait> original{out}; stream_state<Char, Trait> changed; printer<Char, Trait> func(out); const Char percent = out.widen('%'); const Char zero = out.widen('0'); auto&& loc = out.getloc(); size_t index = 0; size_t position = 0; bool has_positional = false; while(*str != 0) { // not a % if(!Trait::eq(*str, percent)) { out << *str++; continue; } // at this point -- *str == '%' // so just increment it to get to the format-spec ++str; // escaped % if(*str && Trait::eq(*str, percent)) { out << percent; ++str; continue; } // beginning of format-spec changed = original; // check for [parameter], i.e. n$ // or a numeric value for [width] position = parse_integer(str, zero, loc); // check if it's [parameter] rather than [width] if(Trait::eq(*str, out.widen('$'))) { has_positional = true; ++str; } // check for [flags] // they are as follows: // + - equivalent to std::showpos // - - left aligns instead of right align, i.e. std::left // 0 - pad with 0s instead of spaces // '[char] - pad with [char] instead of spaces while(*str) { if(Trait::eq(*str, out.widen('+'))) { changed.flags |= out.showpos; } else if(Trait::eq(*str, out.widen('-'))) { changed.flags |= out.left; } else if(Trait::eq(*str, out.widen('0'))) { changed.fill = out.widen('0'); } else if(Trait::eq(*str, out.widen('\''))) { // the next character is unconditionally the fill character changed.fill = *(++str); } else { // unknown flag, so just exit break; } ++str; } // check for [width] changed.width = parse_integer(str, zero, loc); // check for [precision] if(Trait::eq(*str, out.widen('.'))) { changed.precision = parse_integer(++str, zero, loc); } size_t final_index = has_positional ? position - 1 : index++; // check for verb if(Trait::eq(*str, out.widen('s')) || Trait::eq(*str, out.widen('c'))) { // do nothing since these don't add any extra format specifiers. // many of these are provided as a thin compatibility layer for // the original printf -- albeit strict compatibility is not a requirement here. } else if(Trait::eq(*str, out.widen('f')) || Trait::eq(*str, out.widen('F'))) { changed.flags |= out.fixed; } else if(Trait::eq(*str, out.widen('e'))) { changed.flags |= out.scientific; } else if(Trait::eq(*str, out.widen('E'))) { changed.flags |= out.scientific; changed.flags |= out.uppercase; } else if(Trait::eq(*str, out.widen('g'))) { changed.flags &= ~out.floatfield; } else if(Trait::eq(*str, out.widen('G'))) { changed.flags &= ~out.floatfield; changed.flags |= out.uppercase; } else if(Trait::eq(*str, out.widen('x')) || Trait::eq(*str, out.widen('p'))) { changed.flags |= out.hex; } else if(Trait::eq(*str, out.widen('X'))) { changed.flags |= out.hex; changed.flags |= out.uppercase; } else if(Trait::eq(*str, out.widen('d')) || Trait::eq(*str, out.widen('i')) || Trait::eq(*str, out.widen('u'))) { changed.flags |= out.dec; } else if(Trait::eq(*str, out.widen('o'))) { changed.flags |= out.oct; } else { std::string error = "invalid verb given "; auto narrowed = out.narrow(*str, 0x00); if(narrowed == 0x00) { error.push_back('\''); error.push_back(narrowed); error.push_back('\''); } else { error.append(" (unable to convert to char)"); } throw std::runtime_error(error); } changed.apply(out); apply(args, final_index, func); original.apply(out); ++str; } }
typename std::enable_if< mizuiro::color::is_color< Color >::value, std::basic_ostream< Ch, Traits > & >::type operator<<( std::basic_ostream< Ch, Traits > &_stream, Color const &_color ) { _stream << _stream.widen('('); mizuiro::color::for_each_channel( _color, [ &_color, &_stream ]( auto const _channel ) { _stream << static_cast< mizuiro::detail::promote_type< mizuiro::color::types::channel_value< mizuiro::color::format::get< Color >, std::remove_const_t< decltype( _channel ) > > > >( _color.get( _channel ) ) << // FIXME _stream.widen(','); } ); _stream << _stream.widen(')'); return _stream; }