Home | History | Annotate | Download | only in hidl-util
      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