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
18
19#ifndef BRPC_DESCRIBABLE_H
20#define BRPC_DESCRIBABLE_H
21
22#include <ostream>
23#include "butil/macros.h"
24#include "butil/class_name.h"
25
26namespace brpc {
27
28struct DescribeOptions {
29 DescribeOptions()
30 : verbose(true)
31 , use_html(false)
32 {}
33
34 bool verbose;
35 bool use_html;
36};
37
38class Describable {
39public:
40 virtual ~Describable() {}
41 virtual void Describe(std::ostream& os, const DescribeOptions&) const {
42 os << butil::class_name_str(*this);
43 }
44};
45
46class NonConstDescribable {
47public:
48 virtual ~NonConstDescribable() {}
49 virtual void Describe(std::ostream& os, const DescribeOptions&) {
50 os << butil::class_name_str(*this);
51 }
52};
53
54inline std::ostream& operator<<(std::ostream& os, const Describable& obj) {
55 DescribeOptions options;
56 options.verbose = false;
57 obj.Describe(os, options);
58 return os;
59}
60
61inline std::ostream& operator<<(std::ostream& os,
62 NonConstDescribable& obj) {
63 DescribeOptions options;
64 options.verbose = false;
65 obj.Describe(os, options);
66 return os;
67}
68
69// Append `indent' spaces after each newline.
70// Example:
71// IndentingOStream os1(std::cout, 2);
72// IndentingOStream os2(os1, 2);
73// std::cout << "begin1\nhello" << std::endl << "world\nend1" << std::endl;
74// os1 << "begin2\nhello" << std::endl << "world\nend2" << std::endl;
75// os2 << "begin3\nhello" << std::endl << "world\nend3" << std::endl;
76// Output:
77// begin1
78// hello
79// world
80// end1
81// begin2
82// hello
83// world
84// end2
85// begin3
86// hello
87// world
88// end3
89class IndentingOStream : virtual private std::streambuf, public std::ostream {
90public:
91 IndentingOStream(std::ostream& dest, int indent)
92 : std::ostream(this)
93 , _dest(dest.rdbuf())
94 , _is_at_start_of_line(false)
95 , _indent(indent, ' ')
96 {}
97protected:
98 int overflow(int ch) override {
99 if (_is_at_start_of_line && ch != '\n' ) {
100 _dest->sputn(_indent.data(), _indent.size());
101 }
102 _is_at_start_of_line = (ch == '\n');
103 return _dest->sputc(ch);
104 }
105private:
106 DISALLOW_COPY_AND_ASSIGN(IndentingOStream);
107 std::streambuf* _dest;
108 bool _is_at_start_of_line;
109 std::string _indent;
110};
111
112} // namespace brpc
113
114#endif // BRPC_DESCRIBABLE_H
115