Merge "Track current position in Formatter"
diff --git a/host_utils/Formatter.cpp b/host_utils/Formatter.cpp
index 2268e30..24d690c 100644
--- a/host_utils/Formatter.cpp
+++ b/host_utils/Formatter.cpp
@@ -19,17 +19,18 @@
 #include <assert.h>
 
 #include <android-base/logging.h>
+#include <string>
 #include <vector>
 
 namespace android {
 
-Formatter::Formatter() : mFile(nullptr /* invalid */), mIndentDepth(0), mAtStartOfLine(true) {}
+Formatter::Formatter() : mFile(nullptr /* invalid */), mIndentDepth(0), mCurrentPosition(0) {}
 
 Formatter::Formatter(FILE* file, size_t spacesPerIndent)
     : mFile(file == nullptr ? stdout : file),
       mIndentDepth(0),
       mSpacesPerIndent(spacesPerIndent),
-      mAtStartOfLine(true) {}
+      mCurrentPosition(0) {}
 
 Formatter::~Formatter() {
     if (mFile != stdout) {
@@ -116,34 +117,37 @@
     return this->block(block);
 }
 
-Formatter &Formatter::operator<<(const std::string &out) {
+Formatter& Formatter::operator<<(const std::string& out) {
     const size_t len = out.length();
     size_t start = 0;
     while (start < len) {
         size_t pos = out.find('\n', start);
 
         if (pos == std::string::npos) {
-            if (mAtStartOfLine) {
+            if (mCurrentPosition == 0) {
                 fprintf(mFile, "%*s", (int)(getIndentation()), "");
                 fprintf(mFile, "%s", mLinePrefix.c_str());
-                mAtStartOfLine = false;
+                mCurrentPosition = getIndentation() + mLinePrefix.size();
             }
 
-            output(out.substr(start));
+            std::string sub = out.substr(start);
+            output(sub);
+            mCurrentPosition += sub.size();
             break;
         }
 
-        if (mAtStartOfLine && (pos > start || !mLinePrefix.empty())) {
+        if (mCurrentPosition == 0 && (pos > start || !mLinePrefix.empty())) {
             fprintf(mFile, "%*s", (int)(getIndentation()), "");
             fprintf(mFile, "%s", mLinePrefix.c_str());
+            mCurrentPosition = getIndentation() + mLinePrefix.size();
         }
 
         if (pos == start) {
             fprintf(mFile, "\n");
-            mAtStartOfLine = true;
+            mCurrentPosition = 0;
         } else if (pos > start) {
             output(out.substr(start, pos - start + 1));
-            mAtStartOfLine = true;
+            mCurrentPosition = 0;
         }
 
         start = pos + 1;
@@ -152,52 +156,46 @@
     return *this;
 }
 
+void Formatter::printBlock(const WrappedOutput::Block& block, size_t lineLength) {
+    size_t lineStart = mCurrentPosition ?: (getIndentation() + mLinePrefix.size());
+    size_t blockSize = block.computeSize(false);
+    if (blockSize + lineStart < lineLength) {
+        block.print(*this, false);
+        return;
+    }
+
+    // Everything will not fit on this line. Try to fit it on the next line.
+    blockSize = block.computeSize(true);
+    if ((blockSize + getIndentation() + mSpacesPerIndent + mLinePrefix.size()) < lineLength) {
+        *this << "\n";
+        indent();
+
+        block.print(*this, true);
+
+        unindent();
+        return;
+    }
+
+    if (!block.content.empty()) {
+        // Doesn't have subblocks. This means that the block itself is too big.
+        // Have to print it out.
+        *this << "\n";
+        indent();
+
+        block.print(*this, true);
+
+        unindent();
+        return;
+    }
+
+    // Everything will not fit on this line. Go through all the children
+    for (const WrappedOutput::Block& subBlock : block.blocks) {
+        printBlock(subBlock, lineLength);
+    }
+}
+
 Formatter& Formatter::operator<<(const WrappedOutput& wrappedOutput) {
-    CHECK(mAtStartOfLine) << "This function should only be called at the start of a new line";
-
-    size_t currentPosition = getIndentation();
-    std::function<void(Formatter&, const WrappedOutput::Block&)> printBlock =
-            [&](Formatter& out, const WrappedOutput::Block& block) {
-                size_t blockSize = block.computeSize(false);
-                if (blockSize + currentPosition < wrappedOutput.mLineLength) {
-                    block.print(out, false);
-                    currentPosition += blockSize;
-                    return;
-                }
-
-                // Everything will not fit on this line. Try to fit it on the next line.
-                blockSize = block.computeSize(true);
-                if (blockSize + getIndentation() + mSpacesPerIndent < wrappedOutput.mLineLength) {
-                    out << "\n";
-                    out.indent();
-
-                    block.print(out, true);
-                    currentPosition = getIndentation() + blockSize;
-
-                    out.unindent();
-                    return;
-                }
-
-                if (!block.content.empty()) {
-                    // Doesn't have subblocks. This means that the block itself is too big.
-                    // Have to print it out.
-                    out << "\n";
-                    out.indent();
-
-                    block.print(out, true);
-                    currentPosition = getIndentation() + blockSize;
-
-                    out.unindent();
-                    return;
-                }
-
-                // Everything will not fit on this line. Go through all the children
-                for (const WrappedOutput::Block& subBlock : block.blocks) {
-                    printBlock(out, subBlock);
-                }
-            };
-
-    printBlock(*this, wrappedOutput.mRootBlock);
+    printBlock(wrappedOutput.mRootBlock, wrappedOutput.mLineLength);
 
     return *this;
 }
diff --git a/host_utils/include/hidl-util/Formatter.h b/host_utils/include/hidl-util/Formatter.h
index 5ce2351..3c0e116 100644
--- a/host_utils/include/hidl-util/Formatter.h
+++ b/host_utils/include/hidl-util/Formatter.h
@@ -165,8 +165,6 @@
     Formatter &operator<<(float c);
     Formatter &operator<<(double c);
     Formatter &operator<<(long double c);
-
-    // This assumes that the formatter is currently on a newline
     Formatter& operator<<(const WrappedOutput& wrappedOutput);
 
     // Puts a prefix before each line. This is useful if
@@ -187,10 +185,11 @@
     FILE* mFile;  // invalid if nullptr
     size_t mIndentDepth;
     size_t mSpacesPerIndent;
-    bool mAtStartOfLine;
+    size_t mCurrentPosition;
 
     std::string mLinePrefix;
 
+    void printBlock(const WrappedOutput::Block& block, size_t lineLength);
     void output(const std::string &text) const;
 
     Formatter(const Formatter&) = delete;