1 //===- IndentedOstream.cpp - raw ostream wrapper to indent ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // raw_ostream subclass that keeps track of indentation for textual output
10 // where indentation helps readability.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/Support/IndentedOstream.h"
15 
16 using namespace mlir;
17 
18 raw_indented_ostream &
printReindented(StringRef str)19 mlir::raw_indented_ostream::printReindented(StringRef str) {
20   StringRef output = str;
21   // Skip empty lines.
22   while (!output.empty()) {
23     auto split = output.split('\n');
24     size_t indent = split.first.find_first_not_of(" \t");
25     if (indent != StringRef::npos) {
26       // Set an initial value.
27       leadingWs = indent;
28       break;
29     }
30     output = split.second;
31   }
32   // Determine the maximum indent.
33   StringRef remaining = output;
34   while (!remaining.empty()) {
35     auto split = remaining.split('\n');
36     size_t indent = split.first.find_first_not_of(" \t");
37     if (indent != StringRef::npos)
38       leadingWs = std::min(leadingWs, static_cast<int>(indent));
39     remaining = split.second;
40   }
41   // Print, skipping the empty lines.
42   *this << output;
43   leadingWs = 0;
44   return *this;
45 }
46 
write_impl(const char * ptr,size_t size)47 void mlir::raw_indented_ostream::write_impl(const char *ptr, size_t size) {
48   StringRef str(ptr, size);
49   // Print out indented.
50   auto print = [this](StringRef str) {
51     if (atStartOfLine)
52       os.indent(currentIndent) << str.substr(leadingWs);
53     else
54       os << str.substr(leadingWs);
55   };
56 
57   while (!str.empty()) {
58     size_t idx = str.find('\n');
59     if (idx == StringRef::npos) {
60       if (!str.substr(leadingWs).empty()) {
61         print(str);
62         atStartOfLine = false;
63       }
64       break;
65     }
66 
67     auto split =
68         std::make_pair(str.slice(0, idx), str.slice(idx + 1, StringRef::npos));
69     // Print empty new line without spaces if line only has spaces.
70     if (!split.first.ltrim().empty())
71       print(split.first);
72     os << '\n';
73     atStartOfLine = true;
74     str = split.second;
75   }
76 }
77