123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- // Licensed to the Apache Software Foundation (ASF) under one
- // or more contributor license agreements. See the NOTICE file
- // distributed with this work for additional information
- // regarding copyright ownership. The ASF licenses this file
- // to you under the Apache License, Version 2.0 (the
- // "License"); you may not use this file except in compliance
- // with the License. You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing,
- // software distributed under the License is distributed on an
- // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- // KIND, either express or implied. See the License for the
- // specific language governing permissions and limitations
- // under the License.
- // Date: Thu Nov 22 13:57:56 CST 2012
- #include <inttypes.h>
- #include "butil/iobuf.h"
- #include "butil/binary_printer.h"
- namespace butil {
- static char s_binary_char_map[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F'
- };
- template <typename Appender>
- class BinaryCharPrinter {
- public:
- static const size_t BUF_SIZE = 127;
- explicit BinaryCharPrinter(Appender* a) : _n(0), _appender(a) {}
- ~BinaryCharPrinter() { Flush(); }
- void PushChar(unsigned char c);
- void Flush();
- private:
- uint32_t _n;
- Appender* _appender;
- char _buf[BUF_SIZE];
- };
- template <typename Appender>
- void BinaryCharPrinter<Appender>::Flush() {
- if (_n > 0) {
- _appender->Append(_buf, _n);
- _n = 0;
- }
- }
- template <typename Appender>
- void BinaryCharPrinter<Appender>::PushChar(unsigned char c) {
- if (_n > BUF_SIZE - 3) {
- _appender->Append(_buf, _n);
- _n = 0;
- }
- if (c >= 32 && c <= 126) { // displayable ascii characters
- if (c != '\\') {
- _buf[_n++] = c;
- } else {
- _buf[_n++] = '\\';
- _buf[_n++] = '\\';
- }
- } else {
- _buf[_n++] = '\\';
- switch (c) {
- case '\b': _buf[_n++] = 'b'; break;
- case '\t': _buf[_n++] = 't'; break;
- case '\n': _buf[_n++] = 'n'; break;
- case '\r': _buf[_n++] = 'r'; break;
- default:
- _buf[_n++] = s_binary_char_map[c >> 4];
- _buf[_n++] = s_binary_char_map[c & 0xF];
- break;
- }
- }
- }
- class OStreamAppender {
- public:
- OStreamAppender(std::ostream& os) : _os(&os) {}
- void Append(const char* b, size_t n) { _os->write(b, n); }
- private:
- std::ostream* _os;
- };
- class StringAppender {
- public:
- StringAppender(std::string* str) : _str(str) {}
- void Append(const char* b, size_t n) { _str->append(b, n); }
- private:
- std::string* _str;
- };
- template <typename Appender>
- static void PrintIOBuf(Appender* appender, const IOBuf& b, size_t max_length) {
- BinaryCharPrinter<Appender> printer(appender);
- const size_t n = b.backing_block_num();
- size_t nw = 0;
- for (size_t i = 0; i < n; ++i) {
- StringPiece blk = b.backing_block(i);
- for (size_t j = 0; j < blk.size(); ++j) {
- if (nw >= max_length) {
- printer.Flush();
- char buf[48];
- int len = snprintf(buf, sizeof(buf), "...<skipping %" PRIu64 " bytes>",
- (uint64_t)(b.size() - nw));
- appender->Append(buf, len);
- return;
- }
- ++nw;
- printer.PushChar(blk[j]);
- }
- }
- }
- template <typename Appender>
- static void PrintString(Appender* appender, const StringPiece& s, size_t max_length) {
- BinaryCharPrinter<Appender> printer(appender);
- for (size_t i = 0; i < s.size(); ++i) {
- if (i >= max_length) {
- printer.Flush();
- char buf[48];
- int len = snprintf(buf, sizeof(buf), "...<skipping %" PRIu64 " bytes>",
- (uint64_t)(s.size() - i));
- appender->Append(buf, len);
- return;
- }
- printer.PushChar(s[i]);
- }
- }
- void ToPrintable::Print(std::ostream& os) const {
- OStreamAppender appender(os);
- if (_iobuf) {
- PrintIOBuf(&appender, *_iobuf, _max_length);
- } else if (!_str.empty()) {
- PrintString(&appender, _str, _max_length);
- }
- }
- std::string ToPrintableString(const IOBuf& data, size_t max_length) {
- std::string result;
- StringAppender appender(&result);
- PrintIOBuf(&appender, data, max_length);
- return result;
- }
- std::string ToPrintableString(const StringPiece& data, size_t max_length) {
- std::string result;
- StringAppender appender(&result);
- PrintString(&appender, data, max_length);
- return result;
- }
- std::string ToPrintableString(const void* data, size_t n, size_t max_length) {
- std::string result;
- StringAppender appender(&result);
- PrintString(&appender, StringPiece((const char*)data, n), max_length);
- return result;
- }
- } // namespace butil
|