Line data Source code
1 : /**
2 : * @file PrettyPrinter.cpp
3 : * @copyright (c) 2014 by Petr Zemek (s3rvac@gmail.com) and contributors
4 : * @license BSD, see the @c LICENSE file for more details
5 : * @brief Implementation of the PrettyPrinter class.
6 : */
7 :
8 : #include "PrettyPrinter.h"
9 :
10 : #include "BDictionary.h"
11 : #include "BInteger.h"
12 : #include "BList.h"
13 : #include "BString.h"
14 : #include "Utils.h"
15 :
16 : namespace bencoding {
17 :
18 : /**
19 : * @brief Constructs a printer.
20 : */
21 : PrettyPrinter::PrettyPrinter() = default;
22 :
23 : /**
24 : * @brief Creates a new printer.
25 : */
26 13 : std::unique_ptr<PrettyPrinter> PrettyPrinter::create() {
27 13 : return std::unique_ptr<PrettyPrinter>(new PrettyPrinter());
28 : }
29 :
30 : /**
31 : * @brief Returns a pretty representation of @a data.
32 : *
33 : * @param[in] data Data to return a pretty representation for.
34 : * @param[in] indent A single level of indentation.
35 : */
36 12 : std::string PrettyPrinter::getPrettyRepr(std::shared_ptr<BItem> data,
37 : const std::string &indent) {
38 12 : prettyRepr.clear();
39 12 : indentLevel = indent;
40 12 : currentIndent.clear();
41 12 : data->accept(this);
42 12 : return prettyRepr;
43 : }
44 :
45 : /**
46 : * @brief Stores the current indentation into @c prettyRepr.
47 : */
48 12 : void PrettyPrinter::storeCurrentIndent() {
49 12 : prettyRepr += currentIndent;
50 12 : }
51 :
52 : /**
53 : * @brief Increases the current indentation by a single level.
54 : */
55 6 : void PrettyPrinter::increaseIndentLevel() {
56 6 : currentIndent += indentLevel;
57 6 : }
58 :
59 : /**
60 : * @brief Decreases the current indentation by a single level.
61 : */
62 6 : void PrettyPrinter::decreaseIndentLevel() {
63 18 : currentIndent = currentIndent.substr(0,
64 12 : currentIndent.size() - indentLevel.size());
65 6 : }
66 :
67 4 : void PrettyPrinter::visit(BDictionary *bDictionary) {
68 : //
69 : // Format:
70 : //
71 : // {
72 : // "key1": value1,
73 : // "key2": value2,
74 : // ...
75 : // }
76 : //
77 4 : prettyRepr += "{\n";
78 4 : increaseIndentLevel();
79 4 : bool putComma = false;
80 8 : for (auto &item : *bDictionary) {
81 4 : if (putComma) {
82 1 : prettyRepr += ",\n";
83 : }
84 4 : storeCurrentIndent();
85 4 : item.first->accept(this);
86 4 : prettyRepr += ": ";
87 4 : item.second->accept(this);
88 4 : putComma = true;
89 : }
90 4 : if (!bDictionary->empty()) {
91 3 : prettyRepr += "\n";
92 : }
93 4 : decreaseIndentLevel();
94 4 : storeCurrentIndent();
95 4 : prettyRepr += "}";
96 4 : }
97 :
98 7 : void PrettyPrinter::visit(BInteger *bInteger) {
99 : //
100 : // Format (the same with and without indentation):
101 : //
102 : // int
103 : //
104 7 : prettyRepr += std::to_string(bInteger->value());
105 7 : }
106 :
107 2 : void PrettyPrinter::visit(BList *bList) {
108 : //
109 : // Format:
110 : //
111 : // [
112 : // item1,
113 : // item2,
114 : // ...
115 : // ]
116 : //
117 2 : prettyRepr += "[\n";
118 2 : increaseIndentLevel();
119 2 : bool putComma = false;
120 4 : for (auto bItem : *bList) {
121 2 : if (putComma) {
122 1 : prettyRepr += ",\n";
123 : }
124 2 : storeCurrentIndent();
125 2 : bItem->accept(this);
126 2 : putComma = true;
127 : }
128 2 : if (!bList->empty()) {
129 1 : prettyRepr += "\n";
130 : }
131 2 : decreaseIndentLevel();
132 2 : storeCurrentIndent();
133 2 : prettyRepr += "]";
134 2 : }
135 :
136 9 : void PrettyPrinter::visit(BString *bString) {
137 : //
138 : // Format (the same with and without indentation):
139 : //
140 : // "string"
141 : //
142 : // We have to put a backslash before quotes, i.e. replace " with \".
143 9 : prettyRepr += '"' + replace(bString->value(), '"', std::string(R"(\")")) + '"';
144 9 : }
145 :
146 : /**
147 : * @brief Returns a pretty representation of @a data.
148 : *
149 : * This function can be handy if you just want to pretty-print data without
150 : * explicitly creating a pretty printer and calling @c encode() on it.
151 : *
152 : * See PrettyPrinter::getPrettyRepr() for more details.
153 : */
154 1 : std::string getPrettyRepr(std::shared_ptr<BItem> data,
155 : const std::string &indent) {
156 2 : auto prettyPrinter = PrettyPrinter::create();
157 2 : return prettyPrinter->getPrettyRepr(data, indent);
158 : }
159 :
160 : } // namespace bencoding
|