blob: a4f204730325b1fcba0fa786cc02f740001883fd [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "Formatter.h"
18
19#include <assert.h>
20
Andreas Huberc9410c72016-07-28 12:18:40 -070021namespace android {
22
Andreas Huber881227d2016-08-02 14:20:21 -070023Formatter::Formatter(FILE *file)
24 : mFile(file == NULL ? stdout : file),
25 mIndentDepth(0),
Andreas Huberc9410c72016-07-28 12:18:40 -070026 mAtStartOfLine(true) {
27}
28
Andreas Huber881227d2016-08-02 14:20:21 -070029Formatter::~Formatter() {
30 if (mFile != stdout) {
31 fclose(mFile);
32 }
33 mFile = NULL;
34}
35
Yifan Hong0a68a282016-10-21 16:32:34 -070036void Formatter::indent(size_t level) {
37 mIndentDepth += level;
Andreas Huberc9410c72016-07-28 12:18:40 -070038}
39
Yifan Hong0a68a282016-10-21 16:32:34 -070040void Formatter::unindent(size_t level) {
41 assert(mIndentDepth >= level);
42 mIndentDepth -= level;
43}
44
Yifan Honga018ed52016-12-13 16:35:08 -080045Formatter &Formatter::indent(size_t level, std::function<void(void)> func) {
Yifan Hong0a68a282016-10-21 16:32:34 -070046 this->indent(level);
47 func();
48 this->unindent(level);
Yifan Honga018ed52016-12-13 16:35:08 -080049 return *this;
Yifan Hong0a68a282016-10-21 16:32:34 -070050}
51
Yifan Honga018ed52016-12-13 16:35:08 -080052Formatter &Formatter::indent(std::function<void(void)> func) {
53 return this->indent(1, func);
54}
55
56Formatter &Formatter::block(std::function<void(void)> func) {
57 (*this) << "{\n";
58 this->indent(func);
59 return (*this) << "}";
Andreas Huberc9410c72016-07-28 12:18:40 -070060}
61
Yifan Hong20096992016-09-28 17:16:04 -070062void Formatter::setLinePrefix(const std::string &prefix) {
63 mLinePrefix = prefix;
64}
65
66void Formatter::unsetLinePrefix() {
67 mLinePrefix = "";
68}
69
Yifan Honga018ed52016-12-13 16:35:08 -080070Formatter &Formatter::endl() {
71 return (*this) << "\n";
72}
73
74Formatter &Formatter::sIf(const std::string &cond, std::function<void(void)> block) {
75 (*this) << "if (" << cond << ") ";
76 return this->block(block);
77}
78
79Formatter &Formatter::sElseIf(const std::string &cond, std::function<void(void)> block) {
80 (*this) << " else if (" << cond << ") ";
81 return this->block(block);
82}
83
84Formatter &Formatter::sElse(std::function<void(void)> block) {
85 (*this) << " else ";
86 return this->block(block);
87}
88
Yifan Hong31f07ff2017-03-21 18:56:35 +000089Formatter &Formatter::sFor(const std::string &stmts, std::function<void(void)> block) {
90 (*this) << "for (" << stmts << ") ";
91 return this->block(block);
92}
93
Yifan Honge45b5302017-02-22 10:49:07 -080094Formatter &Formatter::sTry(std::function<void(void)> block) {
95 (*this) << "try ";
96 return this->block(block);
97}
98
99Formatter &Formatter::sCatch(const std::string &exception, std::function<void(void)> block) {
100 (*this) << " catch (" << exception << ") ";
101 return this->block(block);
102}
103
Martijn Coenen4de083b2017-03-16 18:49:43 +0100104Formatter &Formatter::sFinally(std::function<void(void)> block) {
105 (*this) << " finally ";
106 return this->block(block);
107}
108
Yifan Hong31f07ff2017-03-21 18:56:35 +0000109Formatter &Formatter::sWhile(const std::string &cond, std::function<void(void)> block) {
110 (*this) << "while (" << cond << ") ";
111 return this->block(block);
112}
113
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700114Formatter &Formatter::operator<<(const std::string &out) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700115 const size_t len = out.length();
116 size_t start = 0;
117 while (start < len) {
118 size_t pos = out.find("\n", start);
119
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700120 if (pos == std::string::npos) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700121 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -0700122 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -0700123 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -0700124 mAtStartOfLine = false;
125 }
126
Andreas Huber0e00de42016-08-03 09:56:02 -0700127 output(out.substr(start));
Andreas Huberc9410c72016-07-28 12:18:40 -0700128 break;
129 }
130
131 if (pos == start) {
Andreas Huber881227d2016-08-02 14:20:21 -0700132 fprintf(mFile, "\n");
Andreas Huberc9410c72016-07-28 12:18:40 -0700133 mAtStartOfLine = true;
134 } else if (pos > start) {
135 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -0700136 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -0700137 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -0700138 }
139
Andreas Huber0e00de42016-08-03 09:56:02 -0700140 output(out.substr(start, pos - start + 1));
Andreas Huberc9410c72016-07-28 12:18:40 -0700141
142 mAtStartOfLine = true;
143 }
144
145 start = pos + 1;
146 }
147
148 return *this;
149}
150
Yifan Hong8d8ae4b2017-04-03 11:33:22 -0700151#define FORMATTER_INPUT_INTEGER(__type__) \
152 Formatter &Formatter::operator<<(__type__ n) { \
153 return (*this) << std::to_string(n); \
154 } \
155
156FORMATTER_INPUT_INTEGER(short);
157FORMATTER_INPUT_INTEGER(unsigned short);
158FORMATTER_INPUT_INTEGER(int);
159FORMATTER_INPUT_INTEGER(unsigned int);
160FORMATTER_INPUT_INTEGER(long);
161FORMATTER_INPUT_INTEGER(unsigned long);
162FORMATTER_INPUT_INTEGER(long long);
163FORMATTER_INPUT_INTEGER(unsigned long long);
164FORMATTER_INPUT_INTEGER(float);
165FORMATTER_INPUT_INTEGER(double);
166FORMATTER_INPUT_INTEGER(long double);
167
168#undef FORMATTER_INPUT_INTEGER
169
170#define FORMATTER_INPUT_CHAR(__type__) \
171 Formatter &Formatter::operator<<(__type__ c) { \
172 return (*this) << std::string(1, (char)c); \
173 } \
174
175FORMATTER_INPUT_CHAR(char);
176FORMATTER_INPUT_CHAR(signed char);
177FORMATTER_INPUT_CHAR(unsigned char);
178
179#undef FORMATTER_INPUT_CHAR
Andreas Huberc9410c72016-07-28 12:18:40 -0700180
Andreas Huber0e00de42016-08-03 09:56:02 -0700181void Formatter::setNamespace(const std::string &space) {
182 mSpace = space;
Andreas Huber0e00de42016-08-03 09:56:02 -0700183}
184
185void Formatter::output(const std::string &text) const {
186 const size_t spaceLength = mSpace.size();
187 if (spaceLength > 0) {
188 // Remove all occurences of "mSpace" and output the filtered result.
189 size_t matchPos = text.find(mSpace);
190 if (matchPos != std::string::npos) {
191 std::string newText = text.substr(0, matchPos);
192 size_t startPos = matchPos + spaceLength;
193 while ((matchPos = text.find(mSpace, startPos))
194 != std::string::npos) {
195 newText.append(text.substr(startPos, matchPos - startPos));
196 startPos = matchPos + spaceLength;
197 }
198 newText.append(text.substr(startPos));
199 fprintf(mFile, "%s", newText.c_str());
200 return;
201 }
202 }
203
204 fprintf(mFile, "%s", text.c_str());
205}
206
Andreas Huberc9410c72016-07-28 12:18:40 -0700207} // namespace android