inline void hex_dump(const void* aData, std::size_t aLength, std::basic_ostream<Elem, Traits>& aStream, std::size_t aWidth = 16) { const char* const start = static_cast<const char*>(aData); const char* const end = start + aLength; const char* line = start; while (line != end) { aStream.width(4); aStream.fill('0'); aStream << std::hex << line - start << " : "; std::size_t lineLength = std::min(aWidth, static_cast<std::size_t>(end - line)); for (std::size_t pass = 1; pass <= 2; ++pass) { for (const char* next = line; next != end && next != line + aWidth; ++next) { char ch = *next; switch(pass) { case 1: aStream << (ch < 32 ? '.' : ch); break; case 2: if (next != line) aStream << " "; aStream.width(2); aStream.fill('0'); aStream << std::hex << std::uppercase << static_cast<int>(static_cast<unsigned char>(ch)); break; } } if (pass == 1 && lineLength != aWidth) aStream << std::string(aWidth - lineLength, ' '); aStream << " "; } aStream << std::endl; line = line + lineLength; } }
inline bool handle_width(std::basic_ostream<CharT, Traits>& o, const T& t) { std::streamsize width = o.width(); if(width == 0) return false; std::basic_ostringstream<CharT, Traits> ss; ss.copyfmt(o); ss.tie(0); ss.width(0); ss << t; o << ss.str(); return true; }
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) { const std::size_t size = str.size(); const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size; const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left; if (!align_left) { detail::insert_fill_chars(os, alignment_size); if (os.good()) os.write(str.data(), size); } else { os.write(str.data(), size); if (os.good()) detail::insert_fill_chars(os, alignment_size); } }
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; } } }