void write_json_helper(std::basic_ostream<typename Ptree::char_type> &stream, const Ptree &pt, int indent) { typedef typename Ptree::char_type Ch; typedef typename std::basic_string<Ch> Str; // Value or object or array if (indent > 0 && pt.empty()) { // Write value Str data = create_escapes(pt.template get_own<Str>(), stream.getloc()); stream << Ch('"') << data << Ch('"'); } else if (indent > 0 && pt.count(Str()) == pt.size()) { // Write array stream << Ch('[') << Ch('\n'); typename Ptree::const_iterator it = pt.begin(); for (; it != pt.end(); ++it) { stream << Str(4 * (indent + 1), Ch(' ')); write_json_helper(stream, it->second, indent + 1); if (boost::next(it) != pt.end()) stream << Ch(','); stream << Ch('\n'); } stream << Str(4 * indent, Ch(' ')) << Ch(']'); } else { // Write object stream << Ch('{') << Ch('\n'); typename Ptree::const_iterator it = pt.begin(); for (; it != pt.end(); ++it) { stream << Str(4 * (indent + 1), Ch(' ')); stream << Ch('"') << create_escapes(it->first, stream.getloc()) << Ch('"') << Ch(':'); if (it->second.empty()) stream << Ch(' '); else stream << Ch('\n') << Str(4 * (indent + 1), Ch(' ')); write_json_helper(stream, it->second, indent + 1); if (boost::next(it) != pt.end()) stream << Ch(','); stream << Ch('\n'); } stream << Str(4 * indent, Ch(' ')) << Ch('}'); } }
/// /// Translate message and write to stream \a out, using imbued locale and domain set to the /// stream /// void write(std::basic_ostream<char_type> &out) const { std::locale const &loc = out.getloc(); int id = ios_info::get(out).domain_id(); string_type buffer; out << write(loc,id,buffer); }
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; } }