11aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber/*
21aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Copyright (C) 2016 The Android Open Source Project
31aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
41aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
51aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * you may not use this file except in compliance with the License.
61aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * You may obtain a copy of the License at
71aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
81aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
91aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
101aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Unless required by applicable law or agreed to in writing, software
111aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
121aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * See the License for the specific language governing permissions and
141aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * limitations under the License.
151aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber */
161aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber
17c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber#include "Formatter.h"
18c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
19c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber#include <assert.h>
20c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
21c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Hubernamespace android {
22c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
23881227d860c59471eee31d39946e96ce2daa35d6Andreas HuberFormatter::Formatter(FILE *file)
24881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    : mFile(file == NULL ? stdout : file),
25881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber      mIndentDepth(0),
26c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber      mAtStartOfLine(true) {
27c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber}
28c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
29881227d860c59471eee31d39946e96ce2daa35d6Andreas HuberFormatter::~Formatter() {
30881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (mFile != stdout) {
31881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber        fclose(mFile);
32881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
33881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    mFile = NULL;
34881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber}
35881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber
360a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hongvoid Formatter::indent(size_t level) {
370a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    mIndentDepth += level;
38c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber}
39c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
400a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hongvoid Formatter::unindent(size_t level) {
410a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    assert(mIndentDepth >= level);
420a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    mIndentDepth -= level;
430a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong}
440a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong
45a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::indent(size_t level, std::function<void(void)> func) {
460a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    this->indent(level);
470a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    func();
480a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong    this->unindent(level);
49a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return *this;
50a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong}
51a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong
52a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::indent(std::function<void(void)> func) {
53a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return this->indent(1, func);
540a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong}
550a68a28cde91706a64b0465b24c7171f9f4cde99Yifan Hong
56a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::block(std::function<void(void)> func) {
57a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    (*this) << "{\n";
58a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    this->indent(func);
59a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return (*this) << "}";
60c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber}
61c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
622009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hongvoid Formatter::setLinePrefix(const std::string &prefix) {
632009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong    mLinePrefix = prefix;
642009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong}
652009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong
662009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hongvoid Formatter::unsetLinePrefix() {
672009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong    mLinePrefix = "";
682009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong}
692009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong
70a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::endl() {
71a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return (*this) << "\n";
72a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong}
73a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong
74a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::sIf(const std::string &cond, std::function<void(void)> block) {
75a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    (*this) << "if (" << cond << ") ";
76a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return this->block(block);
77a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong}
78a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong
79a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::sElseIf(const std::string &cond, std::function<void(void)> block) {
80a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    (*this) << " else if (" << cond << ") ";
81a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return this->block(block);
82a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong}
83a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong
84a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan HongFormatter &Formatter::sElse(std::function<void(void)> block) {
85a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    (*this) << " else ";
86a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong    return this->block(block);
87a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong}
88a018ed53b332ed0d184ae4c53e89a2036f117b58Yifan Hong
8931f07ffea072ad066bc73181f3368951ba21f50dYifan HongFormatter &Formatter::sFor(const std::string &stmts, std::function<void(void)> block) {
9031f07ffea072ad066bc73181f3368951ba21f50dYifan Hong    (*this) << "for (" << stmts << ") ";
9131f07ffea072ad066bc73181f3368951ba21f50dYifan Hong    return this->block(block);
9231f07ffea072ad066bc73181f3368951ba21f50dYifan Hong}
9331f07ffea072ad066bc73181f3368951ba21f50dYifan Hong
94e45b5303e072043679483a70606f6c00dde17382Yifan HongFormatter &Formatter::sTry(std::function<void(void)> block) {
95e45b5303e072043679483a70606f6c00dde17382Yifan Hong    (*this) << "try ";
96e45b5303e072043679483a70606f6c00dde17382Yifan Hong    return this->block(block);
97e45b5303e072043679483a70606f6c00dde17382Yifan Hong}
98e45b5303e072043679483a70606f6c00dde17382Yifan Hong
99e45b5303e072043679483a70606f6c00dde17382Yifan HongFormatter &Formatter::sCatch(const std::string &exception, std::function<void(void)> block) {
100e45b5303e072043679483a70606f6c00dde17382Yifan Hong    (*this) << " catch (" << exception << ") ";
101e45b5303e072043679483a70606f6c00dde17382Yifan Hong    return this->block(block);
102e45b5303e072043679483a70606f6c00dde17382Yifan Hong}
103e45b5303e072043679483a70606f6c00dde17382Yifan Hong
1044de083b1791414410fd9add633ccbb8e56b15036Martijn CoenenFormatter &Formatter::sFinally(std::function<void(void)> block) {
1054de083b1791414410fd9add633ccbb8e56b15036Martijn Coenen    (*this) << " finally ";
1064de083b1791414410fd9add633ccbb8e56b15036Martijn Coenen    return this->block(block);
1074de083b1791414410fd9add633ccbb8e56b15036Martijn Coenen}
1084de083b1791414410fd9add633ccbb8e56b15036Martijn Coenen
10931f07ffea072ad066bc73181f3368951ba21f50dYifan HongFormatter &Formatter::sWhile(const std::string &cond, std::function<void(void)> block) {
11031f07ffea072ad066bc73181f3368951ba21f50dYifan Hong    (*this) << "while (" << cond << ") ";
11131f07ffea072ad066bc73181f3368951ba21f50dYifan Hong    return this->block(block);
11231f07ffea072ad066bc73181f3368951ba21f50dYifan Hong}
11331f07ffea072ad066bc73181f3368951ba21f50dYifan Hong
1145158db484e5ab302368f191d75d5b1334c270e52Zhuoyao ZhangFormatter &Formatter::operator<<(const std::string &out) {
115c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber    const size_t len = out.length();
116c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber    size_t start = 0;
117c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber    while (start < len) {
118c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        size_t pos = out.find("\n", start);
119c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
1205158db484e5ab302368f191d75d5b1334c270e52Zhuoyao Zhang        if (pos == std::string::npos) {
121c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            if (mAtStartOfLine) {
1222009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong                fprintf(mFile, "%s", mLinePrefix.c_str());
123b06cc82425d035b14e4d86a50d5980b836f067fdYifan Hong                fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
124c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber                mAtStartOfLine = false;
125c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            }
126c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
1270e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            output(out.substr(start));
128c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            break;
129c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        }
130c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
131c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        if (pos == start) {
132881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber            fprintf(mFile, "\n");
133c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            mAtStartOfLine = true;
134c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        } else if (pos > start) {
135c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            if (mAtStartOfLine) {
1362009699f1106709cf4bfb281e78efb4f3d04f1c6Yifan Hong                fprintf(mFile, "%s", mLinePrefix.c_str());
137b06cc82425d035b14e4d86a50d5980b836f067fdYifan Hong                fprintf(mFile, "%*s", (int)(4 * mIndentDepth), "");
138c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            }
139c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
1400e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            output(out.substr(start, pos - start + 1));
141c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
142c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber            mAtStartOfLine = true;
143c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        }
144c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
145c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber        start = pos + 1;
146c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber    }
147c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
148c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber    return *this;
149c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber}
150c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
1516b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong#define FORMATTER_INPUT_INTEGER(__type__)               \
1526b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong    Formatter &Formatter::operator<<(__type__ n) {      \
1536b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong        return (*this) << std::to_string(n);            \
1546b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong    }                                                   \
1556b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong
1566b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(short);
1576b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(unsigned short);
1586b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(int);
1596b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(unsigned int);
1606b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(long);
1616b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(unsigned long);
1626b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(long long);
1636b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(unsigned long long);
1646b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(float);
1656b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(double);
1666b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_INTEGER(long double);
1676b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong
1686b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong#undef FORMATTER_INPUT_INTEGER
1696b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong
1706b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong#define FORMATTER_INPUT_CHAR(__type__)                  \
1716b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong    Formatter &Formatter::operator<<(__type__ c) {      \
1726b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong        return (*this) << std::string(1, (char)c);    \
1736b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong    }                                                   \
1746b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong
1756b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_CHAR(char);
1766b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_CHAR(signed char);
1776b7f0700d3771e552964cf24ab9887275c310c4bYifan HongFORMATTER_INPUT_CHAR(unsigned char);
1786b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong
1796b7f0700d3771e552964cf24ab9887275c310c4bYifan Hong#undef FORMATTER_INPUT_CHAR
180c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber
1810e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Hubervoid Formatter::setNamespace(const std::string &space) {
1820e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber    mSpace = space;
1830e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber}
1840e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber
1850e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Hubervoid Formatter::output(const std::string &text) const {
1860e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber    const size_t spaceLength = mSpace.size();
1870e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber    if (spaceLength > 0) {
1880e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber        // Remove all occurences of "mSpace" and output the filtered result.
1890e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber        size_t matchPos = text.find(mSpace);
1900e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber        if (matchPos != std::string::npos) {
1910e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            std::string newText = text.substr(0, matchPos);
1920e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            size_t startPos = matchPos + spaceLength;
1930e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            while ((matchPos = text.find(mSpace, startPos))
1940e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber                    != std::string::npos) {
1950e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber                newText.append(text.substr(startPos, matchPos - startPos));
1960e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber                startPos = matchPos + spaceLength;
1970e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            }
1980e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            newText.append(text.substr(startPos));
1990e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            fprintf(mFile, "%s", newText.c_str());
2000e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber            return;
2010e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber        }
2020e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber    }
2030e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber
2040e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber    fprintf(mFile, "%s", text.c_str());
2050e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber}
2060e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas Huber
207c9410c7e62a33fd7599b2f3e025093a2d171577eAndreas Huber}  // namespace android
208