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