193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski/*
293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * Copyright (C) 2017 The Android Open Source Project
393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski *
493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * you may not use this file except in compliance with the License.
693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * You may obtain a copy of the License at
793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski *
893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski *
1093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * Unless required by applicable law or agreed to in writing, software
1193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * See the License for the specific language governing permissions and
1493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski * limitations under the License.
1593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski */
1693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
1793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include "text/Printer.h"
1893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
1993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include <algorithm>
2093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
2193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include "io/Util.h"
2293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
2393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskiusing ::aapt::io::OutputStream;
2493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskiusing ::android::StringPiece;
2593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
2693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskinamespace aapt {
2793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskinamespace text {
2893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
29a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam LesinskiPrinter& Printer::Println(const StringPiece& str) {
3093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  Print(str);
31a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski  return Print("\n");
3293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}
3393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
34a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam LesinskiPrinter& Printer::Println() {
35a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski  return Print("\n");
3693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}
3793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
38a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam LesinskiPrinter& Printer::Print(const StringPiece& str) {
3993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  if (error_) {
40a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski    return *this;
4193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  }
4293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
4393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  auto remaining_str_begin = str.begin();
4493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  const auto remaining_str_end = str.end();
4593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  while (remaining_str_end != remaining_str_begin) {
4693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    // Find the next new-line.
4793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    const auto new_line_iter = std::find(remaining_str_begin, remaining_str_end, '\n');
4893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
4993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    // We will copy the string up until the next new-line (or end of string).
5093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    const StringPiece str_to_copy = str.substr(remaining_str_begin, new_line_iter);
5193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    if (!str_to_copy.empty()) {
5293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      if (needs_indent_) {
5393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski        for (int i = 0; i < indent_level_; i++) {
5493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski          if (!io::Copy(out_, "  ")) {
5593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski            error_ = true;
56a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski            return *this;
5793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski          }
5893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski        }
5993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski        needs_indent_ = false;
6093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      }
6193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
6293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      if (!io::Copy(out_, str_to_copy)) {
6393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski        error_ = true;
64a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski        return *this;
6593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      }
6693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    }
6793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
6893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    // If we found a new-line.
6993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    if (new_line_iter != remaining_str_end) {
7093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      if (!io::Copy(out_, "\n")) {
7193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski        error_ = true;
72a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski        return *this;
7393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      }
7493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      needs_indent_ = true;
7593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      // Ok to increment iterator here because we know that the '\n' character is one byte.
7693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      remaining_str_begin = new_line_iter + 1;
7793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    } else {
7893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      remaining_str_begin = new_line_iter;
7993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski    }
8093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  }
81a693c4a32ebed4e96dcc1cf6a706e8ebbb004db2Adam Lesinski  return *this;
8293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}
8393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
8493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskivoid Printer::Indent() {
8593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  ++indent_level_;
8693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}
8793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
8893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskivoid Printer::Undent() {
8993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  --indent_level_;
9093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}
9193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
9293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}  // namespace text
9393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski}  // namespace aapt
94