blob: a261fb419cb9e895c2b9530dc5e07bd10cc2f9d3 [file] [log] [blame]
Paul Stewartb9b3f9d2014-09-10 15:12:39 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chromeos-dbus-bindings/indented_text.h"
6
7#include <string>
8#include <utility>
9#include <vector>
10
11#include <base/logging.h>
Alex Vakulenko0a865142014-11-26 08:44:50 -080012#include <base/strings/string_util.h>
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080013#include <chromeos/strings/string_utils.h>
Paul Stewartb9b3f9d2014-09-10 15:12:39 -070014
15using std::string;
16using std::vector;
17
18namespace chromeos_dbus_bindings {
19
20IndentedText::IndentedText() : offset_(0) {}
21
Paul Stewart8d62c292014-10-01 05:40:57 -070022void IndentedText::AddBlankLine() {
23 AddLine("");
24}
25
Paul Stewartb9b3f9d2014-09-10 15:12:39 -070026void IndentedText::AddBlock(const IndentedText& block) {
27 AddBlockWithOffset(block, 0);
28}
29
30void IndentedText::AddBlockWithOffset(const IndentedText& block, size_t shift) {
31 for (const auto& member : block.contents_) {
32 AddLineWithOffset(member.first, member.second + shift);
33 }
34}
35
36void IndentedText::AddLine(const std::string& line) {
37 AddLineWithOffset(line, 0);
38}
39
40void IndentedText::AddLineWithOffset(const std::string& line, size_t shift) {
41 contents_.emplace_back(line, shift + offset_);
42}
43
Alex Vakulenko99e8fb02014-12-01 17:22:03 -080044void IndentedText::AddLineAndPushOffsetTo(const std::string& line,
45 size_t occurrence,
46 char c) {
47 AddLine(line);
48 size_t pos = 0;
49 while (occurrence > 0) {
50 pos = line.find(c, pos);
51 CHECK(pos != string::npos);
52 pos++;
53 occurrence--;
54 }
55 PushOffset(pos);
56}
57
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -080058void IndentedText::AddComments(const std::string& doc_string) {
Alex Vakulenko0a865142014-11-26 08:44:50 -080059 // Try to retain indentation in the comments. Find the first non-empty line
60 // of the comment and find its whitespace indentation prefix.
61 // For all subsequent lines, remove the same whitespace prefix as found
62 // at the first line of the comment but keep any additional spaces to
63 // maintain the comment layout.
64 auto lines = chromeos::string_utils::Split(doc_string, '\n', false, false);
65 vector<string> lines_out;
66 lines_out.reserve(lines.size());
67 bool first_nonempty_found = false;
68 std::string trim_prefix;
69 for (string line : lines) {
70 base::TrimWhitespaceASCII(line, base::TRIM_TRAILING, &line);
71 if (!first_nonempty_found) {
72 size_t pos = line.find_first_not_of(" \t");
73 if (pos != std::string::npos) {
74 first_nonempty_found = true;
75 trim_prefix = line.substr(0, pos);
76 lines_out.push_back(line.substr(pos));
77 }
78 } else {
79 if (StartsWithASCII(line, trim_prefix, false)) {
80 line = line.substr(trim_prefix.length());
81 } else {
82 base::TrimWhitespaceASCII(line, base::TRIM_LEADING, &line);
83 }
84 lines_out.push_back(line);
85 }
86 }
87
88 // We already eliminated all empty lines at the beginning of the comment
89 // block. Now remove the trailing empty lines.
90 while (!lines_out.empty() && lines_out.back().empty())
91 lines_out.pop_back();
92
93 for (const string& line : lines_out) {
94 const bool all_whitespace = (line.find_first_not_of(" \t") == string::npos);
95 if (all_whitespace) {
96 AddLine("//");
97 } else {
98 AddLine("// " + line);
99 }
Alex Vakulenko4f3c05e2014-11-12 15:01:46 -0800100 }
101}
102
Paul Stewartb9b3f9d2014-09-10 15:12:39 -0700103string IndentedText::GetContents() const {
104 string output;
105 for (const auto& member : contents_) {
Paul Stewart8d62c292014-10-01 05:40:57 -0700106 const string& line = member.first;
107 size_t shift = line.empty() ? 0 : member.second;
108 string indent(shift, ' ');
109 output.append(indent + line + "\n");
Paul Stewartb9b3f9d2014-09-10 15:12:39 -0700110 }
111 return output;
112}
113
114void IndentedText::PushOffset(size_t shift) {
115 offset_ += shift;
116 offset_history_.push_back(shift);
117}
118
119void IndentedText::PopOffset() {
120 CHECK(!offset_history_.empty());
121 offset_ -= offset_history_.back();
122 offset_history_.pop_back();
123}
124
125void IndentedText::Reset() {
126 offset_ = 0;
127 offset_history_.clear();
128 contents_.clear();
129}
130
131} // namespace chromeos_dbus_bindings