binary_printer.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // Date: Thu Nov 22 13:57:56 CST 2012
  18. #include <inttypes.h>
  19. #include "butil/iobuf.h"
  20. #include "butil/binary_printer.h"
  21. namespace butil {
  22. static char s_binary_char_map[] = {
  23. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  24. 'A', 'B', 'C', 'D', 'E', 'F'
  25. };
  26. template <typename Appender>
  27. class BinaryCharPrinter {
  28. public:
  29. static const size_t BUF_SIZE = 127;
  30. explicit BinaryCharPrinter(Appender* a) : _n(0), _appender(a) {}
  31. ~BinaryCharPrinter() { Flush(); }
  32. void PushChar(unsigned char c);
  33. void Flush();
  34. private:
  35. uint32_t _n;
  36. Appender* _appender;
  37. char _buf[BUF_SIZE];
  38. };
  39. template <typename Appender>
  40. void BinaryCharPrinter<Appender>::Flush() {
  41. if (_n > 0) {
  42. _appender->Append(_buf, _n);
  43. _n = 0;
  44. }
  45. }
  46. template <typename Appender>
  47. void BinaryCharPrinter<Appender>::PushChar(unsigned char c) {
  48. if (_n > BUF_SIZE - 3) {
  49. _appender->Append(_buf, _n);
  50. _n = 0;
  51. }
  52. if (c >= 32 && c <= 126) { // displayable ascii characters
  53. if (c != '\\') {
  54. _buf[_n++] = c;
  55. } else {
  56. _buf[_n++] = '\\';
  57. _buf[_n++] = '\\';
  58. }
  59. } else {
  60. _buf[_n++] = '\\';
  61. switch (c) {
  62. case '\b': _buf[_n++] = 'b'; break;
  63. case '\t': _buf[_n++] = 't'; break;
  64. case '\n': _buf[_n++] = 'n'; break;
  65. case '\r': _buf[_n++] = 'r'; break;
  66. default:
  67. _buf[_n++] = s_binary_char_map[c >> 4];
  68. _buf[_n++] = s_binary_char_map[c & 0xF];
  69. break;
  70. }
  71. }
  72. }
  73. class OStreamAppender {
  74. public:
  75. OStreamAppender(std::ostream& os) : _os(&os) {}
  76. void Append(const char* b, size_t n) { _os->write(b, n); }
  77. private:
  78. std::ostream* _os;
  79. };
  80. class StringAppender {
  81. public:
  82. StringAppender(std::string* str) : _str(str) {}
  83. void Append(const char* b, size_t n) { _str->append(b, n); }
  84. private:
  85. std::string* _str;
  86. };
  87. template <typename Appender>
  88. static void PrintIOBuf(Appender* appender, const IOBuf& b, size_t max_length) {
  89. BinaryCharPrinter<Appender> printer(appender);
  90. const size_t n = b.backing_block_num();
  91. size_t nw = 0;
  92. for (size_t i = 0; i < n; ++i) {
  93. StringPiece blk = b.backing_block(i);
  94. for (size_t j = 0; j < blk.size(); ++j) {
  95. if (nw >= max_length) {
  96. printer.Flush();
  97. char buf[48];
  98. int len = snprintf(buf, sizeof(buf), "...<skipping %" PRIu64 " bytes>",
  99. (uint64_t)(b.size() - nw));
  100. appender->Append(buf, len);
  101. return;
  102. }
  103. ++nw;
  104. printer.PushChar(blk[j]);
  105. }
  106. }
  107. }
  108. template <typename Appender>
  109. static void PrintString(Appender* appender, const StringPiece& s, size_t max_length) {
  110. BinaryCharPrinter<Appender> printer(appender);
  111. for (size_t i = 0; i < s.size(); ++i) {
  112. if (i >= max_length) {
  113. printer.Flush();
  114. char buf[48];
  115. int len = snprintf(buf, sizeof(buf), "...<skipping %" PRIu64 " bytes>",
  116. (uint64_t)(s.size() - i));
  117. appender->Append(buf, len);
  118. return;
  119. }
  120. printer.PushChar(s[i]);
  121. }
  122. }
  123. void ToPrintable::Print(std::ostream& os) const {
  124. OStreamAppender appender(os);
  125. if (_iobuf) {
  126. PrintIOBuf(&appender, *_iobuf, _max_length);
  127. } else if (!_str.empty()) {
  128. PrintString(&appender, _str, _max_length);
  129. }
  130. }
  131. std::string ToPrintableString(const IOBuf& data, size_t max_length) {
  132. std::string result;
  133. StringAppender appender(&result);
  134. PrintIOBuf(&appender, data, max_length);
  135. return result;
  136. }
  137. std::string ToPrintableString(const StringPiece& data, size_t max_length) {
  138. std::string result;
  139. StringAppender appender(&result);
  140. PrintString(&appender, data, max_length);
  141. return result;
  142. }
  143. std::string ToPrintableString(const void* data, size_t n, size_t max_length) {
  144. std::string result;
  145. StringAppender appender(&result);
  146. PrintString(&appender, StringPiece((const char*)data, n), max_length);
  147. return result;
  148. }
  149. } // namespace butil