Squashed 'third_party/ctemplate/' content from commit 6742f62
Change-Id: I828e4e4c906f13ba19944d78a8a78652b62949af
git-subtree-dir: third_party/ctemplate
git-subtree-split: 6742f6233db12f545e90baa8f34f5c29c4eb396a
diff --git a/src/indented_writer.h b/src/indented_writer.h
new file mode 100644
index 0000000..6df190e
--- /dev/null
+++ b/src/indented_writer.h
@@ -0,0 +1,134 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: williasr@google.com (Scott Williams)
+
+#ifndef TEMPLATE_INDENTED_WRITER_H_
+#define TEMPLATE_INDENTED_WRITER_H_
+
+#include <config.h>
+#include <string>
+
+namespace ctemplate {
+
+using std::string;
+
+// An indented writer is a wrapper around a string buffer. It takes care of
+// tracking and applying leading whitespace to the buffer at the beginning of
+// new lines.
+class IndentedWriter {
+ public:
+ IndentedWriter(string* out, int starting_indentation)
+ : out_(out), current_indentation_(starting_indentation),
+ original_indentation_(starting_indentation), line_state_(AT_BEGINNING) { }
+
+ ~IndentedWriter() {
+ assert(original_indentation_ == current_indentation_);
+ }
+
+ // Append some output to the buffer. If the string ends with a newline, then
+ // the output buffer will be indented before the next Write() call. If the
+ // output contains embedded newlines, these won't have proper indentation, so
+ // call Write() at least once per physical line of output.
+ void Write(string s1,
+ string s2 = string(),
+ string s3 = string(),
+ string s4 = string(),
+ string s5 = string(),
+ string s6 = string(),
+ string s7 = string()) {
+ DoWrite(s1);
+ if (!s2.empty()) DoWrite(s2);
+ if (!s3.empty()) DoWrite(s3);
+ if (!s4.empty()) DoWrite(s4);
+ if (!s5.empty()) DoWrite(s5);
+ if (!s6.empty()) DoWrite(s6);
+ if (!s7.empty()) DoWrite(s7);
+ }
+
+ // Increment the indentation level. This only has a meaning after outputting a
+ // complete line (otherwise, are you saying you want to modify the indentation
+ // of the current line or the next line?)
+ void Indent() {
+ assert(line_state_ == AT_BEGINNING);
+ current_indentation_ += kIndent;
+ }
+
+ // Decrement the indentation level. This only has a meaning after outputting a
+ // complete line (otherwise, are you saying you want to modify the indentation
+ // of the current line or the next line?)
+ void Dedent() {
+ assert(line_state_ == AT_BEGINNING);
+ current_indentation_ -= kIndent;
+ assert(current_indentation_ >= original_indentation_);
+ }
+
+ // Get access to the underlying indentation level and string buffer. Most
+ // useful for interfacing with non-IndentedWriter printing code.
+ int GetIndent() const { return current_indentation_; }
+ string* GetBuffer() { return out_; }
+
+ private:
+ void DoWrite(const string& line) {
+ if (line_state_ == AT_BEGINNING) {
+ IndentLine();
+ }
+ out_->append(line);
+ if (EndsWithNewline(line)) {
+ line_state_ = AT_BEGINNING;
+ } else {
+ line_state_ = MID_LINE;
+ }
+ }
+
+ static bool EndsWithNewline(const string& line) {
+ return !line.empty() && (*(line.end() - 1) == '\n');
+ }
+
+ void IndentLine() {
+ assert(line_state_ == AT_BEGINNING);
+ out_->append(string(current_indentation_, ' ') +
+ (current_indentation_ ? " " : ""));
+ }
+
+ string* out_;
+ int current_indentation_;
+ int original_indentation_;
+ enum LineState {
+ AT_BEGINNING,
+ MID_LINE
+ } line_state_;
+
+ const static int kIndent = 2; // num spaces to indent each level
+};
+
+}
+
+#endif // TEMPLATE_INDENTED_WRITER_H_