1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/
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// Utility class for writing text to a ZeroCopyOutputStream.
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define GOOGLE_PROTOBUF_IO_PRINTER_H__
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <string>
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <map>
42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <vector>
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/common.h>
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace io {
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass ZeroCopyOutputStream;     // zero_copy_stream.h
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Records annotations about a Printer's output.
52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerclass LIBPROTOBUF_EXPORT AnnotationCollector {
53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public:
54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Records that the bytes in file_path beginning with begin_offset and ending
55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // before end_offset are associated with the SourceCodeInfo-style path.
56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             const string& file_path,
58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             const vector<int>& path) = 0;
59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  virtual ~AnnotationCollector() {}
61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Records annotations about a Printer's output to the given protocol buffer,
64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// assuming that the buffer has an ::Annotation message exposing path,
65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// source_file, begin and end fields.
66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertemplate <typename AnnotationProto>
67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerclass AnnotationProtoCollector : public AnnotationCollector {
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public:
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // annotation_proto is the protocol buffer to which new Annotations should be
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // added. It is not owned by the AnnotationProtoCollector.
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      : annotation_proto_(annotation_proto) {}
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Override for AnnotationCollector::AddAnnotation.
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             const string& file_path, const vector<int>& path) {
77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    typename AnnotationProto::Annotation* annotation =
78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        annotation_proto_->add_annotation();
79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (int i = 0; i < path.size(); ++i) {
80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      annotation->add_path(path[i]);
81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    annotation->set_source_file(file_path);
83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    annotation->set_begin(begin_offset);
84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    annotation->set_end(end_offset);
85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private:
88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // The protocol buffer to which new annotations should be added.
89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  AnnotationProto* const annotation_proto_;
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// This simple utility class assists in code generation.  It basically
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// allows the caller to define a set of variables and then output some
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// text with variable substitutions.  Example usage:
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   Printer printer(output, '$');
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   map<string, string> vars;
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   vars["name"] = "Bob";
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//   printer.Print(vars, "My name is $name$.");
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// The above writes "My name is Bob." to the output stream.
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Printer aggressively enforces correct usage, crashing (with assert failures)
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// in the case of undefined variables in debug builds. This helps greatly in
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// debugging code which uses it.
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// If a Printer is constructed with an AnnotationCollector, it will provide it
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// with annotations that connect the Printer's output to paths that can identify
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// various descriptors.  In the above example, if person_ is a descriptor that
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// identifies Bob, we can associate the output string "My name is Bob." with
111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// a source path pointing to that descriptor with:
112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Annotate("name", person_);
114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// The AnnotationCollector will be sent an annotation linking the output range
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// covering "Bob" to the logical path provided by person_.  Tools may use
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this association to (for example) link "Bob" in the output back to the
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// source file that defined the person_ descriptor identifying Bob.
119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Annotate can only examine variables substituted during the last call to
121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Print.  It is invalid to refer to a variable that was used multiple times
122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in a single Print call.
123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// In full generality, one may specify a range of output text using a beginning
125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// substitution variable and an ending variable.  The resulting annotation will
126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// span from the first character of the substituted value for the beginning
127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// variable to the last character of the substituted value for the ending
128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// variable.  For example, the Annotate call above is equivalent to this one:
129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Annotate("name", "name", person_);
131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// This is useful if multiple variables combine to form a single span of output
133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// that should be annotated with the same source path.  For example:
134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   Printer printer(output, '$');
136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   map<string, string> vars;
137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   vars["first"] = "Alice";
138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   vars["last"] = "Smith";
139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Print(vars, "My name is $first$ $last$.");
140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Annotate("first", "last", person_);
141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// This code would associate the span covering "Alice Smith" in the output with
143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// the person_ descriptor.
144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Note that the beginning variable must come before (or overlap with, in the
146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// case of zero-sized substitution values) the ending variable.
147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// It is also sometimes useful to use variables with zero-sized values as
149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// markers.  This avoids issues with multiple references to the same variable
150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// and also allows annotation ranges to span literal text from the Print
151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// templates:
152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   Printer printer(output, '$');
154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   map<string, string> vars;
155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   vars["foo"] = "bar";
156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   vars["function"] = "call";
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   vars["mark"] = "";
158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Print(vars, "$function$($foo$,$foo$)$mark$");
159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//   printer.Annotate("function", "rmark", call_);
160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer//
161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// This code associates the span covering "call(bar,bar)" in the output with the
162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// call_ descriptor.
163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass LIBPROTOBUF_EXPORT Printer {
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public:
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Create a printer that writes text to the given output stream.  Use the
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // given character as the delimiter for variables.
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Printer(ZeroCopyOutputStream* output, char variable_delimiter);
169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Create a printer that writes text to the given output stream.  Use the
171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // given character as the delimiter for variables.  If annotation_collector
172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // is not null, Printer will provide it with annotations about code written
173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // to the stream.  annotation_collector is not owned by Printer.
174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  Printer(ZeroCopyOutputStream* output, char variable_delimiter,
175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          AnnotationCollector* annotation_collector);
176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ~Printer();
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Link a subsitution variable emitted by the last call to Print to the object
180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // described by descriptor.
181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  template <typename SomeDescriptor>
182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Annotate(const char* varname, const SomeDescriptor* descriptor) {
183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    Annotate(varname, varname, descriptor);
184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Link the output range defined by the substitution variables as emitted by
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // the last call to Print to the object described by descriptor. The range
188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // begins at begin_varname's value and ends after the last character of the
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // value substituted for end_varname.
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  template <typename SomeDescriptor>
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Annotate(const char* begin_varname, const char* end_varname,
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                const SomeDescriptor* descriptor) {
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (annotation_collector_ == NULL) {
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Annotations aren't turned on for this Printer, so don't pay the cost
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // of building the location path.
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return;
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    vector<int> path;
199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    descriptor->GetLocationPath(&path);
200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Print some text after applying variable substitutions.  If a particular
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // variable in the text is not defined, this will crash.  Variables to be
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // substituted are identified by their names surrounded by delimiter
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // characters (as given to the constructor).  The variable bindings are
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // defined by the given map.
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Print(const map<string, string>& variables, const char* text);
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Like the first Print(), except the substitutions are given as parameters.
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Print(const char* text);
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Like the first Print(), except the substitutions are given as parameters.
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Print(const char* text, const char* variable, const string& value);
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Like the first Print(), except the substitutions are given as parameters.
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Print(const char* text, const char* variable1, const string& value1,
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                               const char* variable2, const string& value2);
217a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Like the first Print(), except the substitutions are given as parameters.
218a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  void Print(const char* text, const char* variable1, const string& value1,
219a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson                               const char* variable2, const string& value2,
220a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson                               const char* variable3, const string& value3);
221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Like the first Print(), except the substitutions are given as parameters.
222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Print(const char* text, const char* variable1, const string& value1,
223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable2, const string& value2,
224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable3, const string& value3,
225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable4, const string& value4);
226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Like the first Print(), except the substitutions are given as parameters.
227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Print(const char* text, const char* variable1, const string& value1,
228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable2, const string& value2,
229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable3, const string& value3,
230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable4, const string& value4,
231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable5, const string& value5);
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Like the first Print(), except the substitutions are given as parameters.
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Print(const char* text, const char* variable1, const string& value1,
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable2, const string& value2,
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable3, const string& value3,
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable4, const string& value4,
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable5, const string& value5,
238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable6, const string& value6);
239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Like the first Print(), except the substitutions are given as parameters.
240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Print(const char* text, const char* variable1, const string& value1,
241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable2, const string& value2,
242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable3, const string& value3,
243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable4, const string& value4,
244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable5, const string& value5,
245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable6, const string& value6,
246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable7, const string& value7);
247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Like the first Print(), except the substitutions are given as parameters.
248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Print(const char* text, const char* variable1, const string& value1,
249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable2, const string& value2,
250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable3, const string& value3,
251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable4, const string& value4,
252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable5, const string& value5,
253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable6, const string& value6,
254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable7, const string& value7,
255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const char* variable8, const string& value8);
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Indent text by two spaces.  After calling Indent(), two spaces will be
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // inserted at the beginning of each line of text.  Indent() may be called
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // multiple times to produce deeper indents.
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Indent();
261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Reduces the current indent level by two spaces, or crashes if the indent
263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // level is zero.
264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  void Outdent();
265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Write a string to the output buffer.
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // This method does not look for newlines to add indentation.
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void PrintRaw(const string& data);
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Write a zero-delimited string to output buffer.
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // This method does not look for newlines to add indentation.
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void PrintRaw(const char* data);
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // Write some bytes to the output buffer.
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // This method does not look for newlines to add indentation.
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  void WriteRaw(const char* data, int size);
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // True if any write to the underlying stream failed.  (We don't just
279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // crash in this case because this is an I/O failure, not a programming
280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // error.)
281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool failed() const { return failed_; }
282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private:
284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Link the output range defined by the substitution variables as emitted by
285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // the last call to Print to the object found at the SourceCodeInfo-style path
286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // in a file with path file_path. The range begins at the start of
287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // begin_varname's value and ends after the last character of the value
288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // substituted for end_varname. Note that begin_varname and end_varname
289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // may refer to the same variable.
290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void Annotate(const char* begin_varname, const char* end_varname,
291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                const string& file_path, const vector<int>& path);
292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const char variable_delimiter_;
294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ZeroCopyOutputStream* const output_;
296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  char* buffer_;
297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  int buffer_size_;
298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // The current position, in bytes, in the output stream.  This is equivalent
299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // to the total number of bytes that have been written so far.  This value is
300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // used to calculate annotation ranges in the substitutions_ map below.
301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t offset_;
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  string indent_;
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool at_start_of_line_;
305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  bool failed_;
306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // A map from variable name to [start, end) offsets in the output buffer.
308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // These refer to the offsets used for a variable after the last call to
309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Print.  If a variable was used more than once, the entry used in
310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // this map is set to a negative-length span.  For singly-used variables, the
311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // start offset is the beginning of the substitution; the end offset is the
312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // last byte of the substitution plus one (such that (end - start) is the
313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // length of the substituted string).
314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  map<string, pair<size_t, size_t> > substitutions_;
315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Returns true and sets range to the substitution range in the output for
317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // varname if varname was used once in the last call to Print. If varname
318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // was not used, or if it was used multiple times, returns false (and
319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // fails a debug assertion).
320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool GetSubstitutionRange(const char* varname, pair<size_t, size_t>* range);
321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // If non-null, annotation_collector_ is used to store annotations about
323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // generated code.
324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  AnnotationCollector* const annotation_collector_;
325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville};
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace io
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif  // GOOGLE_PROTOBUF_IO_PRINTER_H__
334