blob: db763d980aebf2bdb5f15989300c86dc1c0062c2 [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 Honge45b5302017-02-22 10:49:07 -080089Formatter &Formatter::sTry(std::function<void(void)> block) {
90 (*this) << "try ";
91 return this->block(block);
92}
93
94Formatter &Formatter::sCatch(const std::string &exception, std::function<void(void)> block) {
95 (*this) << " catch (" << exception << ") ";
96 return this->block(block);
97}
98
Martijn Coenen4de083b2017-03-16 18:49:43 +010099Formatter &Formatter::sFinally(std::function<void(void)> block) {
100 (*this) << " finally ";
101 return this->block(block);
102}
103
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700104Formatter &Formatter::operator<<(const std::string &out) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700105 const size_t len = out.length();
106 size_t start = 0;
107 while (start < len) {
108 size_t pos = out.find("\n", start);
109
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700110 if (pos == std::string::npos) {
Andreas Huberc9410c72016-07-28 12:18:40 -0700111 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -0700112 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -0700113 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -0700114 mAtStartOfLine = false;
115 }
116
Andreas Huber0e00de42016-08-03 09:56:02 -0700117 output(out.substr(start));
Andreas Huberc9410c72016-07-28 12:18:40 -0700118 break;
119 }
120
121 if (pos == start) {
Andreas Huber881227d2016-08-02 14:20:21 -0700122 fprintf(mFile, "\n");
Andreas Huberc9410c72016-07-28 12:18:40 -0700123 mAtStartOfLine = true;
124 } else if (pos > start) {
125 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -0700126 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -0700127 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -0700128 }
129
Andreas Huber0e00de42016-08-03 09:56:02 -0700130 output(out.substr(start, pos - start + 1));
Andreas Huberc9410c72016-07-28 12:18:40 -0700131
132 mAtStartOfLine = true;
133 }
134
135 start = pos + 1;
136 }
137
138 return *this;
139}
140
141Formatter &Formatter::operator<<(size_t n) {
142 return (*this) << std::to_string(n);
143}
144
Andreas Huber0e00de42016-08-03 09:56:02 -0700145void Formatter::setNamespace(const std::string &space) {
146 mSpace = space;
Andreas Huber0e00de42016-08-03 09:56:02 -0700147}
148
149void Formatter::output(const std::string &text) const {
150 const size_t spaceLength = mSpace.size();
151 if (spaceLength > 0) {
152 // Remove all occurences of "mSpace" and output the filtered result.
153 size_t matchPos = text.find(mSpace);
154 if (matchPos != std::string::npos) {
155 std::string newText = text.substr(0, matchPos);
156 size_t startPos = matchPos + spaceLength;
157 while ((matchPos = text.find(mSpace, startPos))
158 != std::string::npos) {
159 newText.append(text.substr(startPos, matchPos - startPos));
160 startPos = matchPos + spaceLength;
161 }
162 newText.append(text.substr(startPos));
163 fprintf(mFile, "%s", newText.c_str());
164 return;
165 }
166 }
167
168 fprintf(mFile, "%s", text.c_str());
169}
170
Andreas Huberc9410c72016-07-28 12:18:40 -0700171} // namespace android