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 #ifndef FORMATTER_H_ 18 19 #define FORMATTER_H_ 20 21 #include <functional> 22 #include <string> 23 24 namespace android { 25 26 // Two styles to use a Formatter. 27 // One is with .indent() calls and operator<<. 28 // out << "if (good) {\n"; out.indent(); out << "blah\nblah\n"; out.unindent(); out << "}\n"; 29 // The other is with chain calls and lambda functions 30 // out.sIf("good", [&] { out("blah").endl()("blah").endl(); }).endl(); 31 struct Formatter { 32 static Formatter invalid() { return Formatter(); } 33 34 // Assumes ownership of file. Directed to stdout if file == NULL. 35 Formatter(FILE* file, size_t spacesPerIndent = 4); 36 Formatter(Formatter&&) = default; 37 ~Formatter(); 38 39 void indent(size_t level = 1); 40 void unindent(size_t level = 1); 41 42 // Note that The last \n after the last line is NOT added automatically. 43 // out.indent(2, [&] { 44 // out << "Meow\n"; 45 // }); 46 Formatter& indent(size_t level, const std::function<void(void)>& func); 47 48 // Note that The last \n after the last line is NOT added automatically. 49 // out.indent([&] { 50 // out << "Meow\n"; 51 // }); 52 Formatter& indent(const std::function<void(void)>& func); 53 54 // A block inside braces. 55 // * No space will be added before the opening brace. 56 // * The last \n before the closing brace is added automatically. 57 // * There will NOT be a \n after the closing brace. 58 // out.block([&] { 59 // out << "one();\n" 60 // << "two();\n"; 61 // }); 62 // is equivalent to 63 // out << "{\n" 64 // << "one();\ntwo();\n" // func() 65 // << "}"; 66 Formatter& block(const std::function<void(void)>& func); 67 68 // A synonym to (*this) << "\n"; 69 Formatter &endl(); 70 71 // out.sIf("z == 1", [&] { 72 // out << "doGoodStuff();\n"; 73 // }).sElseIf("z == 2", [&] { 74 // out << "doBadStuff();\n"; 75 // }).sElse([&] { 76 // out << "logFatal();\n"; 77 // }).endl(); 78 // note that there will be a space before the "else"-s. 79 Formatter& sIf(const std::string& cond, const std::function<void(void)>& block); 80 Formatter& sElseIf(const std::string& cond, const std::function<void(void)>& block); 81 Formatter& sElse(const std::function<void(void)>& block); 82 83 // out.sFor("int i = 0; i < 10; i++", [&] { 84 // out << "printf(\"%d\", i);\n"; 85 // }).endl(); 86 Formatter& sFor(const std::string& stmts, const std::function<void(void)>& block); 87 88 // out.sTry([&] { 89 // out << "throw RemoteException();\n" 90 // }).sCatch("RemoteException ex", [&] { 91 // out << "ex.printStackTrace();\n" 92 // }).sFinally([&] { 93 // // cleanup 94 // }).endl(); 95 // note that there will be a space before the "catch"-s. 96 Formatter& sTry(const std::function<void(void)>& block); 97 Formatter& sCatch(const std::string& exception, const std::function<void(void)>& block); 98 Formatter& sFinally(const std::function<void(void)>& block); 99 100 // out.sWhile("z < 10", [&] { 101 // out << "z++;\n"; 102 // }).endl(); 103 Formatter& sWhile(const std::string& cond, const std::function<void(void)>& block); 104 105 // out.join(v.begin(), v.end(), ",", [&](const auto &e) { 106 // out << toString(e); 107 // }); 108 template <typename I> 109 Formatter& join( 110 const I begin, const I end, const std::string& separator, 111 const std::function<void(const typename std::iterator_traits<I>::value_type&)>& func); 112 113 Formatter &operator<<(const std::string &out); 114 115 Formatter &operator<<(char c); 116 Formatter &operator<<(signed char c); 117 Formatter &operator<<(unsigned char c); 118 119 Formatter &operator<<(short c); 120 Formatter &operator<<(unsigned short c); 121 Formatter &operator<<(int c); 122 Formatter &operator<<(unsigned int c); 123 Formatter &operator<<(long c); 124 Formatter &operator<<(unsigned long c); 125 Formatter &operator<<(long long c); 126 Formatter &operator<<(unsigned long long c); 127 Formatter &operator<<(float c); 128 Formatter &operator<<(double c); 129 Formatter &operator<<(long double c); 130 131 // Any substrings matching "space" will be stripped out of the output. 132 void setNamespace(const std::string &space); 133 134 // Puts a prefix before each line. This is useful if 135 // you want to start a // comment block, for example. 136 // The prefix will be put before the indentation. 137 // Will be effective the next time cursor is at the start of line. 138 void setLinePrefix(const std::string& prefix); 139 // Remove the line prefix. 140 void unsetLinePrefix(); 141 142 bool isValid() const; 143 144 private: 145 // Creates an invalid formatter object. 146 Formatter(); 147 148 FILE* mFile; // invalid if nullptr 149 size_t mIndentDepth; 150 size_t mSpacesPerIndent; 151 bool mAtStartOfLine; 152 153 std::string mSpace; 154 std::string mLinePrefix; 155 156 void output(const std::string &text) const; 157 158 Formatter(const Formatter&) = delete; 159 void operator=(const Formatter&) = delete; 160 }; 161 162 template <typename I> 163 Formatter& Formatter::join( 164 const I begin, const I end, const std::string& separator, 165 const std::function<void(const typename std::iterator_traits<I>::value_type&)>& func) { 166 for (I iter = begin; iter != end; ++iter) { 167 if (iter != begin) { 168 (*this) << separator; 169 } 170 func(*iter); 171 } 172 return (*this); 173 } 174 175 } // namespace android 176 177 #endif // FORMATTER_H_ 178 179