PageRenderTime 44ms CodeModel.GetById 14ms app.highlight 24ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/io/printer.cc

http://github.com/tomahawk-player/tomahawk
C++ | 199 lines | 123 code | 28 blank | 48 comment | 23 complexity | 8214cead30538c97582bdeadfa2d1377 MD5 | raw file
  1// Protocol Buffers - Google's data interchange format
  2// Copyright 2008 Google Inc.  All rights reserved.
  3// http://code.google.com/p/protobuf/
  4//
  5// Redistribution and use in source and binary forms, with or without
  6// modification, are permitted provided that the following conditions are
  7// met:
  8//
  9//     * Redistributions of source code must retain the above copyright
 10// notice, this list of conditions and the following disclaimer.
 11//     * Redistributions in binary form must reproduce the above
 12// copyright notice, this list of conditions and the following disclaimer
 13// in the documentation and/or other materials provided with the
 14// distribution.
 15//     * Neither the name of Google Inc. nor the names of its
 16// contributors may be used to endorse or promote products derived from
 17// this software without specific prior written permission.
 18//
 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30
 31// Author: kenton@google.com (Kenton Varda)
 32//  Based on original Protocol Buffers design by
 33//  Sanjay Ghemawat, Jeff Dean, and others.
 34
 35#include <google/protobuf/io/printer.h>
 36#include <google/protobuf/io/zero_copy_stream.h>
 37#include <google/protobuf/stubs/common.h>
 38#include <google/protobuf/stubs/strutil.h>
 39
 40namespace google {
 41namespace protobuf {
 42namespace io {
 43
 44Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
 45  : variable_delimiter_(variable_delimiter),
 46    output_(output),
 47    buffer_(NULL),
 48    buffer_size_(0),
 49    at_start_of_line_(true),
 50    failed_(false) {
 51}
 52
 53Printer::~Printer() {
 54  // Only BackUp() if we're sure we've successfully called Next() at least once.
 55  if (buffer_size_ > 0) {
 56    output_->BackUp(buffer_size_);
 57  }
 58}
 59
 60void Printer::Print(const map<string, string>& variables, const char* text) {
 61  int size = strlen(text);
 62  int pos = 0;  // The number of bytes we've written so far.
 63
 64  for (int i = 0; i < size; i++) {
 65    if (text[i] == '\n') {
 66      // Saw newline.  If there is more text, we may need to insert an indent
 67      // here.  So, write what we have so far, including the '\n'.
 68      WriteRaw(text + pos, i - pos + 1);
 69      pos = i + 1;
 70
 71      // Setting this true will cause the next WriteRaw() to insert an indent
 72      // first.
 73      at_start_of_line_ = true;
 74
 75    } else if (text[i] == variable_delimiter_) {
 76      // Saw the start of a variable name.
 77
 78      // Write what we have so far.
 79      WriteRaw(text + pos, i - pos);
 80      pos = i + 1;
 81
 82      // Find closing delimiter.
 83      const char* end = strchr(text + pos, variable_delimiter_);
 84      if (end == NULL) {
 85        GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
 86        end = text + pos;
 87      }
 88      int endpos = end - text;
 89
 90      string varname(text + pos, endpos - pos);
 91      if (varname.empty()) {
 92        // Two delimiters in a row reduce to a literal delimiter character.
 93        WriteRaw(&variable_delimiter_, 1);
 94      } else {
 95        // Replace with the variable's value.
 96        map<string, string>::const_iterator iter = variables.find(varname);
 97        if (iter == variables.end()) {
 98          GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
 99        } else {
100          WriteRaw(iter->second.data(), iter->second.size());
101        }
102      }
103
104      // Advance past this variable.
105      i = endpos;
106      pos = endpos + 1;
107    }
108  }
109
110  // Write the rest.
111  WriteRaw(text + pos, size - pos);
112}
113
114void Printer::Print(const char* text) {
115  static map<string, string> empty;
116  Print(empty, text);
117}
118
119void Printer::Print(const char* text,
120                    const char* variable, const string& value) {
121  map<string, string> vars;
122  vars[variable] = value;
123  Print(vars, text);
124}
125
126void Printer::Print(const char* text,
127                    const char* variable1, const string& value1,
128                    const char* variable2, const string& value2) {
129  map<string, string> vars;
130  vars[variable1] = value1;
131  vars[variable2] = value2;
132  Print(vars, text);
133}
134
135void Printer::Print(const char* text,
136                    const char* variable1, const string& value1,
137                    const char* variable2, const string& value2,
138                    const char* variable3, const string& value3) {
139  map<string, string> vars;
140  vars[variable1] = value1;
141  vars[variable2] = value2;
142  vars[variable3] = value3;
143  Print(vars, text);
144}
145
146void Printer::Indent() {
147  indent_ += "  ";
148}
149
150void Printer::Outdent() {
151  if (indent_.empty()) {
152    GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
153    return;
154  }
155
156  indent_.resize(indent_.size() - 2);
157}
158
159void Printer::PrintRaw(const string& data) {
160  WriteRaw(data.data(), data.size());
161}
162
163void Printer::PrintRaw(const char* data) {
164  if (failed_) return;
165  WriteRaw(data, strlen(data));
166}
167
168void Printer::WriteRaw(const char* data, int size) {
169  if (failed_) return;
170  if (size == 0) return;
171
172  if (at_start_of_line_) {
173    // Insert an indent.
174    at_start_of_line_ = false;
175    WriteRaw(indent_.data(), indent_.size());
176    if (failed_) return;
177  }
178
179  while (size > buffer_size_) {
180    // Data exceeds space in the buffer.  Copy what we can and request a
181    // new buffer.
182    memcpy(buffer_, data, buffer_size_);
183    data += buffer_size_;
184    size -= buffer_size_;
185    void* void_buffer;
186    failed_ = !output_->Next(&void_buffer, &buffer_size_);
187    if (failed_) return;
188    buffer_ = reinterpret_cast<char*>(void_buffer);
189  }
190
191  // Buffer is big enough to receive the data; copy it.
192  memcpy(buffer_, data, size);
193  buffer_ += size;
194  buffer_size_ -= size;
195}
196
197}  // namespace io
198}  // namespace protobuf
199}  // namespace google