blob: df3a5a4385bc813bbf5bd81ba67bbecc015c2442 [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
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070089Formatter &Formatter::operator<<(const std::string &out) {
Andreas Huberc9410c72016-07-28 12:18:40 -070090 const size_t len = out.length();
91 size_t start = 0;
92 while (start < len) {
93 size_t pos = out.find("\n", start);
94
Zhuoyao Zhang5158db42016-08-10 10:25:20 -070095 if (pos == std::string::npos) {
Andreas Huberc9410c72016-07-28 12:18:40 -070096 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -070097 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -070098 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -070099 mAtStartOfLine = false;
100 }
101
Andreas Huber0e00de42016-08-03 09:56:02 -0700102 output(out.substr(start));
Andreas Huberc9410c72016-07-28 12:18:40 -0700103 break;
104 }
105
106 if (pos == start) {
Andreas Huber881227d2016-08-02 14:20:21 -0700107 fprintf(mFile, "\n");
Andreas Huberc9410c72016-07-28 12:18:40 -0700108 mAtStartOfLine = true;
109 } else if (pos > start) {
110 if (mAtStartOfLine) {
Yifan Hong20096992016-09-28 17:16:04 -0700111 fprintf(mFile, "%s", mLinePrefix.c_str());
Yifan Hongb06cc822016-09-26 14:36:15 -0700112 fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
Andreas Huberc9410c72016-07-28 12:18:40 -0700113 }
114
Andreas Huber0e00de42016-08-03 09:56:02 -0700115 output(out.substr(start, pos - start + 1));
Andreas Huberc9410c72016-07-28 12:18:40 -0700116
117 mAtStartOfLine = true;
118 }
119
120 start = pos + 1;
121 }
122
123 return *this;
124}
125
126Formatter &Formatter::operator<<(size_t n) {
127 return (*this) << std::to_string(n);
128}
129
Andreas Huber0e00de42016-08-03 09:56:02 -0700130void Formatter::setNamespace(const std::string &space) {
131 mSpace = space;
Andreas Huber0e00de42016-08-03 09:56:02 -0700132}
133
134void Formatter::output(const std::string &text) const {
135 const size_t spaceLength = mSpace.size();
136 if (spaceLength > 0) {
137 // Remove all occurences of "mSpace" and output the filtered result.
138 size_t matchPos = text.find(mSpace);
139 if (matchPos != std::string::npos) {
140 std::string newText = text.substr(0, matchPos);
141 size_t startPos = matchPos + spaceLength;
142 while ((matchPos = text.find(mSpace, startPos))
143 != std::string::npos) {
144 newText.append(text.substr(startPos, matchPos - startPos));
145 startPos = matchPos + spaceLength;
146 }
147 newText.append(text.substr(startPos));
148 fprintf(mFile, "%s", newText.c_str());
149 return;
150 }
151 }
152
153 fprintf(mFile, "%s", text.c_str());
154}
155
Andreas Huberc9410c72016-07-28 12:18:40 -0700156} // namespace android