1 /* 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 17 #include "Formatter.h" 18 19 #include <assert.h> 20 21 #include <android-base/logging.h> 22 23 namespace android { 24 25 Formatter::Formatter() : mFile(NULL /* invalid */), mIndentDepth(0), mAtStartOfLine(true) {} 26 27 Formatter::Formatter(FILE* file, size_t spacesPerIndent) 28 : mFile(file == NULL ? stdout : file), 29 mIndentDepth(0), 30 mSpacesPerIndent(spacesPerIndent), 31 mAtStartOfLine(true) {} 32 33 Formatter::~Formatter() { 34 if (mFile != stdout) { 35 fclose(mFile); 36 } 37 mFile = NULL; 38 } 39 40 void Formatter::indent(size_t level) { 41 mIndentDepth += level; 42 } 43 44 void Formatter::unindent(size_t level) { 45 assert(mIndentDepth >= level); 46 mIndentDepth -= level; 47 } 48 49 Formatter& Formatter::indent(size_t level, const std::function<void(void)>& func) { 50 this->indent(level); 51 func(); 52 this->unindent(level); 53 return *this; 54 } 55 56 Formatter& Formatter::indent(const std::function<void(void)>& func) { 57 return this->indent(1, func); 58 } 59 60 Formatter& Formatter::block(const std::function<void(void)>& func) { 61 (*this) << "{\n"; 62 this->indent(func); 63 return (*this) << "}"; 64 } 65 66 void Formatter::setLinePrefix(const std::string &prefix) { 67 mLinePrefix = prefix; 68 } 69 70 void Formatter::unsetLinePrefix() { 71 mLinePrefix = ""; 72 } 73 74 Formatter &Formatter::endl() { 75 return (*this) << "\n"; 76 } 77 78 Formatter& Formatter::sIf(const std::string& cond, const std::function<void(void)>& block) { 79 (*this) << "if (" << cond << ") "; 80 return this->block(block); 81 } 82 83 Formatter& Formatter::sElseIf(const std::string& cond, const std::function<void(void)>& block) { 84 (*this) << " else if (" << cond << ") "; 85 return this->block(block); 86 } 87 88 Formatter& Formatter::sElse(const std::function<void(void)>& block) { 89 (*this) << " else "; 90 return this->block(block); 91 } 92 93 Formatter& Formatter::sFor(const std::string& stmts, const std::function<void(void)>& block) { 94 (*this) << "for (" << stmts << ") "; 95 return this->block(block); 96 } 97 98 Formatter& Formatter::sTry(const std::function<void(void)>& block) { 99 (*this) << "try "; 100 return this->block(block); 101 } 102 103 Formatter& Formatter::sCatch(const std::string& exception, const std::function<void(void)>& block) { 104 (*this) << " catch (" << exception << ") "; 105 return this->block(block); 106 } 107 108 Formatter& Formatter::sFinally(const std::function<void(void)>& block) { 109 (*this) << " finally "; 110 return this->block(block); 111 } 112 113 Formatter& Formatter::sWhile(const std::string& cond, const std::function<void(void)>& block) { 114 (*this) << "while (" << cond << ") "; 115 return this->block(block); 116 } 117 118 Formatter &Formatter::operator<<(const std::string &out) { 119 const size_t len = out.length(); 120 size_t start = 0; 121 while (start < len) { 122 size_t pos = out.find('\n', start); 123 124 if (pos == std::string::npos) { 125 if (mAtStartOfLine) { 126 fprintf(mFile, "%*s", (int)(mSpacesPerIndent * mIndentDepth), ""); 127 fprintf(mFile, "%s", mLinePrefix.c_str()); 128 mAtStartOfLine = false; 129 } 130 131 output(out.substr(start)); 132 break; 133 } 134 135 if (mAtStartOfLine && (pos > start || !mLinePrefix.empty())) { 136 fprintf(mFile, "%*s", (int)(mSpacesPerIndent * mIndentDepth), ""); 137 fprintf(mFile, "%s", mLinePrefix.c_str()); 138 } 139 140 if (pos == start) { 141 fprintf(mFile, "\n"); 142 mAtStartOfLine = true; 143 } else if (pos > start) { 144 output(out.substr(start, pos - start + 1)); 145 mAtStartOfLine = true; 146 } 147 148 start = pos + 1; 149 } 150 151 return *this; 152 } 153 154 // NOLINT to suppress missing parentheses warning about __type__. 155 #define FORMATTER_INPUT_INTEGER(__type__) \ 156 Formatter& Formatter::operator<<(__type__ n) { /* NOLINT */ \ 157 return (*this) << std::to_string(n); \ 158 } 159 160 FORMATTER_INPUT_INTEGER(short); 161 FORMATTER_INPUT_INTEGER(unsigned short); 162 FORMATTER_INPUT_INTEGER(int); 163 FORMATTER_INPUT_INTEGER(unsigned int); 164 FORMATTER_INPUT_INTEGER(long); 165 FORMATTER_INPUT_INTEGER(unsigned long); 166 FORMATTER_INPUT_INTEGER(long long); 167 FORMATTER_INPUT_INTEGER(unsigned long long); 168 FORMATTER_INPUT_INTEGER(float); 169 FORMATTER_INPUT_INTEGER(double); 170 FORMATTER_INPUT_INTEGER(long double); 171 172 #undef FORMATTER_INPUT_INTEGER 173 174 // NOLINT to suppress missing parentheses warning about __type__. 175 #define FORMATTER_INPUT_CHAR(__type__) \ 176 Formatter& Formatter::operator<<(__type__ c) { /* NOLINT */ \ 177 return (*this) << std::string(1, (char)c); \ 178 } 179 180 FORMATTER_INPUT_CHAR(char); 181 FORMATTER_INPUT_CHAR(signed char); 182 FORMATTER_INPUT_CHAR(unsigned char); 183 184 #undef FORMATTER_INPUT_CHAR 185 186 void Formatter::setNamespace(const std::string &space) { 187 mSpace = space; 188 } 189 190 bool Formatter::isValid() const { 191 return mFile != nullptr; 192 } 193 194 void Formatter::output(const std::string &text) const { 195 CHECK(isValid()); 196 197 fprintf(mFile, "%s", text.c_str()); 198 } 199 200 } // namespace android 201