protobuf/src/google/protobuf/io/printer.h
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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 // Utility class for writing text to a ZeroCopyOutputStream.
36 
37 #ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
38 #define GOOGLE_PROTOBUF_IO_PRINTER_H__
39 
40 
41 #include <map>
42 #include <string>
43 #include <vector>
44 
45 #include <google/protobuf/stubs/common.h>
46 #include <google/protobuf/port_def.inc>
47 
48 namespace google {
49 namespace protobuf {
50 namespace io {
51 
52 class ZeroCopyOutputStream; // zero_copy_stream.h
53 
54 // Records annotations about a Printer's output.
55 class PROTOBUF_EXPORT AnnotationCollector {
56  public:
57  // Annotation is a offset range and a payload pair.
58  typedef std::pair<std::pair<size_t, size_t>, std::string> Annotation;
59 
60  // Records that the bytes in file_path beginning with begin_offset and ending
61  // before end_offset are associated with the SourceCodeInfo-style path.
62  virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
63  const std::string& file_path,
64  const std::vector<int>& path) = 0;
65 
66  // TODO(gerbens) I don't see why we need virtuals here. Just a vector of
67  // range, payload pairs stored in a context should suffice.
68  virtual void AddAnnotationNew(Annotation& /* a */) {}
69 
70  virtual ~AnnotationCollector() {}
71 };
72 
73 // Records annotations about a Printer's output to the given protocol buffer,
74 // assuming that the buffer has an ::Annotation message exposing path,
75 // source_file, begin and end fields.
76 template <typename AnnotationProto>
77 class AnnotationProtoCollector : public AnnotationCollector {
78  public:
79  // annotation_proto is the protocol buffer to which new Annotations should be
80  // added. It is not owned by the AnnotationProtoCollector.
81  explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
82  : annotation_proto_(annotation_proto) {}
83 
84  // Override for AnnotationCollector::AddAnnotation.
85  void AddAnnotation(size_t begin_offset, size_t end_offset,
86  const std::string& file_path,
87  const std::vector<int>& path) override {
88  typename AnnotationProto::Annotation* annotation =
89  annotation_proto_->add_annotation();
90  for (int i = 0; i < path.size(); ++i) {
91  annotation->add_path(path[i]);
92  }
93  annotation->set_source_file(file_path);
94  annotation->set_begin(begin_offset);
95  annotation->set_end(end_offset);
96  }
97  // Override for AnnotationCollector::AddAnnotation.
98  void AddAnnotationNew(Annotation& a) override {
99  auto* annotation = annotation_proto_->add_annotation();
100  annotation->ParseFromString(a.second);
101  annotation->set_begin(a.first.first);
102  annotation->set_end(a.first.second);
103  }
104 
105  private:
106  // The protocol buffer to which new annotations should be added.
107  AnnotationProto* const annotation_proto_;
108 };
109 
110 // This simple utility class assists in code generation. It basically
111 // allows the caller to define a set of variables and then output some
112 // text with variable substitutions. Example usage:
113 //
114 // Printer printer(output, '$');
115 // map<string, string> vars;
116 // vars["name"] = "Bob";
117 // printer.Print(vars, "My name is $name$.");
118 //
119 // The above writes "My name is Bob." to the output stream.
120 //
121 // Printer aggressively enforces correct usage, crashing (with assert failures)
122 // in the case of undefined variables in debug builds. This helps greatly in
123 // debugging code which uses it.
124 //
125 // If a Printer is constructed with an AnnotationCollector, it will provide it
126 // with annotations that connect the Printer's output to paths that can identify
127 // various descriptors. In the above example, if person_ is a descriptor that
128 // identifies Bob, we can associate the output string "My name is Bob." with
129 // a source path pointing to that descriptor with:
130 //
131 // printer.Annotate("name", person_);
132 //
133 // The AnnotationCollector will be sent an annotation linking the output range
134 // covering "Bob" to the logical path provided by person_. Tools may use
135 // this association to (for example) link "Bob" in the output back to the
136 // source file that defined the person_ descriptor identifying Bob.
137 //
138 // Annotate can only examine variables substituted during the last call to
139 // Print. It is invalid to refer to a variable that was used multiple times
140 // in a single Print call.
141 //
142 // In full generality, one may specify a range of output text using a beginning
143 // substitution variable and an ending variable. The resulting annotation will
144 // span from the first character of the substituted value for the beginning
145 // variable to the last character of the substituted value for the ending
146 // variable. For example, the Annotate call above is equivalent to this one:
147 //
148 // printer.Annotate("name", "name", person_);
149 //
150 // This is useful if multiple variables combine to form a single span of output
151 // that should be annotated with the same source path. For example:
152 //
153 // Printer printer(output, '$');
154 // map<string, string> vars;
155 // vars["first"] = "Alice";
156 // vars["last"] = "Smith";
157 // printer.Print(vars, "My name is $first$ $last$.");
158 // printer.Annotate("first", "last", person_);
159 //
160 // This code would associate the span covering "Alice Smith" in the output with
161 // the person_ descriptor.
162 //
163 // Note that the beginning variable must come before (or overlap with, in the
164 // case of zero-sized substitution values) the ending variable.
165 //
166 // It is also sometimes useful to use variables with zero-sized values as
167 // markers. This avoids issues with multiple references to the same variable
168 // and also allows annotation ranges to span literal text from the Print
169 // templates:
170 //
171 // Printer printer(output, '$');
172 // map<string, string> vars;
173 // vars["foo"] = "bar";
174 // vars["function"] = "call";
175 // vars["mark"] = "";
176 // printer.Print(vars, "$function$($foo$,$foo$)$mark$");
177 // printer.Annotate("function", "mark", call_);
178 //
179 // This code associates the span covering "call(bar,bar)" in the output with the
180 // call_ descriptor.
181 
182 class PROTOBUF_EXPORT Printer {
183  public:
184  // Create a printer that writes text to the given output stream. Use the
185  // given character as the delimiter for variables.
186  Printer(ZeroCopyOutputStream* output, char variable_delimiter);
187 
188  // Create a printer that writes text to the given output stream. Use the
189  // given character as the delimiter for variables. If annotation_collector
190  // is not null, Printer will provide it with annotations about code written
191  // to the stream. annotation_collector is not owned by Printer.
192  Printer(ZeroCopyOutputStream* output, char variable_delimiter,
193  AnnotationCollector* annotation_collector);
194 
195  ~Printer();
196 
197  // Link a substitution variable emitted by the last call to Print to the
198  // object described by descriptor.
199  template <typename SomeDescriptor>
200  void Annotate(const char* varname, const SomeDescriptor* descriptor) {
201  Annotate(varname, varname, descriptor);
202  }
203 
204  // Link the output range defined by the substitution variables as emitted by
205  // the last call to Print to the object described by descriptor. The range
206  // begins at begin_varname's value and ends after the last character of the
207  // value substituted for end_varname.
208  template <typename SomeDescriptor>
209  void Annotate(const char* begin_varname, const char* end_varname,
210  const SomeDescriptor* descriptor) {
211  if (annotation_collector_ == NULL) {
212  // Annotations aren't turned on for this Printer, so don't pay the cost
213  // of building the location path.
214  return;
215  }
216  std::vector<int> path;
217  descriptor->GetLocationPath(&path);
218  Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
219  }
220 
221  // Link a substitution variable emitted by the last call to Print to the file
222  // with path file_name.
223  void Annotate(const char* varname, const std::string& file_name) {
224  Annotate(varname, varname, file_name);
225  }
226 
227  // Link the output range defined by the substitution variables as emitted by
228  // the last call to Print to the file with path file_name. The range begins
229  // at begin_varname's value and ends after the last character of the value
230  // substituted for end_varname.
231  void Annotate(const char* begin_varname, const char* end_varname,
232  const std::string& file_name) {
233  if (annotation_collector_ == NULL) {
234  // Annotations aren't turned on for this Printer.
235  return;
236  }
237  std::vector<int> empty_path;
238  Annotate(begin_varname, end_varname, file_name, empty_path);
239  }
240 
241  // Print some text after applying variable substitutions. If a particular
242  // variable in the text is not defined, this will crash. Variables to be
243  // substituted are identified by their names surrounded by delimiter
244  // characters (as given to the constructor). The variable bindings are
245  // defined by the given map.
246  void Print(const std::map<std::string, std::string>& variables,
247  const char* text);
248 
249  // Like the first Print(), except the substitutions are given as parameters.
250  template <typename... Args>
251  void Print(const char* text, const Args&... args) {
252  std::map<std::string, std::string> vars;
253  PrintInternal(&vars, text, args...);
254  }
255 
256  // Indent text by two spaces. After calling Indent(), two spaces will be
257  // inserted at the beginning of each line of text. Indent() may be called
258  // multiple times to produce deeper indents.
259  void Indent();
260 
261  // Reduces the current indent level by two spaces, or crashes if the indent
262  // level is zero.
263  void Outdent();
264 
265  // Write a string to the output buffer.
266  // This method does not look for newlines to add indentation.
267  void PrintRaw(const std::string& data);
268 
269  // Write a zero-delimited string to output buffer.
270  // This method does not look for newlines to add indentation.
271  void PrintRaw(const char* data);
272 
273  // Write some bytes to the output buffer.
274  // This method does not look for newlines to add indentation.
275  void WriteRaw(const char* data, int size);
276 
277  // FormatInternal is a helper function not meant to use directly, use
278  // compiler::cpp::Formatter instead. This function is meant to support
279  // formatting text using named variables (eq. "$foo$) from a lookup map (vars)
280  // and variables directly supplied by arguments (eq "$1$" meaning first
281  // argument which is the zero index element of args).
282  void FormatInternal(const std::vector<std::string>& args,
283  const std::map<std::string, std::string>& vars,
284  const char* format);
285 
286  // True if any write to the underlying stream failed. (We don't just
287  // crash in this case because this is an I/O failure, not a programming
288  // error.)
289  bool failed() const { return failed_; }
290 
291  private:
292  // Link the output range defined by the substitution variables as emitted by
293  // the last call to Print to the object found at the SourceCodeInfo-style path
294  // in a file with path file_path. The range begins at the start of
295  // begin_varname's value and ends after the last character of the value
296  // substituted for end_varname. Note that begin_varname and end_varname
297  // may refer to the same variable.
298  void Annotate(const char* begin_varname, const char* end_varname,
299  const std::string& file_path, const std::vector<int>& path);
300 
301  // Base case
302  void PrintInternal(std::map<std::string, std::string>* vars,
303  const char* text) {
304  Print(*vars, text);
305  }
306 
307  template <typename... Args>
308  void PrintInternal(std::map<std::string, std::string>* vars, const char* text,
309  const char* key, const std::string& value,
310  const Args&... args) {
311  (*vars)[key] = value;
312  PrintInternal(vars, text, args...);
313  }
314 
315  // Copy size worth of bytes from data to buffer_.
316  void CopyToBuffer(const char* data, int size);
317 
318  void push_back(char c) {
319  if (failed_) return;
320  if (buffer_size_ == 0) {
321  if (!Next()) return;
322  }
323  *buffer_++ = c;
324  buffer_size_--;
325  offset_++;
326  }
327 
328  bool Next();
329 
330  inline void IndentIfAtStart();
331  const char* WriteVariable(
332  const std::vector<std::string>& args,
333  const std::map<std::string, std::string>& vars, const char* format,
334  int* arg_index,
335  std::vector<AnnotationCollector::Annotation>* annotations);
336 
337  const char variable_delimiter_;
338 
340  char* buffer_;
341  int buffer_size_;
342  // The current position, in bytes, in the output stream. This is equivalent
343  // to the total number of bytes that have been written so far. This value is
344  // used to calculate annotation ranges in the substitutions_ map below.
345  size_t offset_;
346 
348  bool at_start_of_line_;
349  bool failed_;
350 
351  // A map from variable name to [start, end) offsets in the output buffer.
352  // These refer to the offsets used for a variable after the last call to
353  // Print. If a variable was used more than once, the entry used in
354  // this map is set to a negative-length span. For singly-used variables, the
355  // start offset is the beginning of the substitution; the end offset is the
356  // last byte of the substitution plus one (such that (end - start) is the
357  // length of the substituted string).
358  std::map<std::string, std::pair<size_t, size_t> > substitutions_;
359 
360  // Keeps track of the keys in substitutions_ that need to be updated when
361  // indents are inserted. These are keys that refer to the beginning of the
362  // current line.
363  std::vector<std::string> line_start_variables_;
364 
365  // Returns true and sets range to the substitution range in the output for
366  // varname if varname was used once in the last call to Print. If varname
367  // was not used, or if it was used multiple times, returns false (and
368  // fails a debug assertion).
369  bool GetSubstitutionRange(const char* varname,
370  std::pair<size_t, size_t>* range);
371 
372  // If non-null, annotation_collector_ is used to store annotations about
373  // generated code.
374  AnnotationCollector* const annotation_collector_;
375 
377 };
378 
379 } // namespace io
380 } // namespace protobuf
381 } // namespace google
382 
383 #include <google/protobuf/port_undef.inc>
384 
385 #endif // GOOGLE_PROTOBUF_IO_PRINTER_H__
google::protobuf::io::Printer::PrintInternal
void PrintInternal(std::map< std::string, std::string > *vars, const char *text)
Definition: protobuf/src/google/protobuf/io/printer.h:302
http2_test_server.format
format
Definition: http2_test_server.py:118
google::protobuf::value
const Descriptor::ReservedRange value
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1954
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/macros.h:40
capstone.range
range
Definition: third_party/bloaty/third_party/capstone/bindings/python/capstone/__init__.py:6
testing::internal::Indent
static std::string Indent(size_t width)
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:4122
testing::gtest_printers_test::Print
std::string Print(const T &value)
Definition: bloaty/third_party/googletest/googletest/test/googletest-printers-test.cc:233
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
grpc::protobuf::io::Printer
GRPC_CUSTOM_PRINTER Printer
Definition: src/compiler/config.h:54
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
google::protobuf::io::Printer::PrintInternal
void PrintInternal(std::map< std::string, std::string > *vars, const char *text, const char *key, const std::string &value, const Args &... args)
Definition: protobuf/src/google/protobuf/io/printer.h:308
grpc::protobuf::io::ZeroCopyOutputStream
GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ZeroCopyOutputStream
Definition: include/grpcpp/impl/codegen/config_protobuf.h:100
google::protobuf::io::AnnotationProtoCollector::AnnotationProtoCollector
AnnotationProtoCollector(AnnotationProto *annotation_proto)
Definition: protobuf/src/google/protobuf/io/printer.h:81
check_documentation.path
path
Definition: check_documentation.py:57
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
absl::base_internal::Next
static AllocList * Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena)
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:453
buffer_
static uint8 buffer_[kBufferSize]
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:136
gen_server_registered_method_bad_client_test_body.text
def text
Definition: gen_server_registered_method_bad_client_test_body.py:50
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
google::protobuf::io::Printer::push_back
void push_back(char c)
Definition: protobuf/src/google/protobuf/io/printer.h:318
hpack_encoder_fixtures::Args
Args({0, 16384})
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
google::protobuf::io::Printer::Annotate
void Annotate(const char *begin_varname, const char *end_varname, const SomeDescriptor *descriptor)
Definition: protobuf/src/google/protobuf/io/printer.h:209
google::protobuf::compiler::php::Outdent
void Outdent(io::Printer *printer)
Definition: third_party/bloaty/third_party/protobuf/src/google/protobuf/compiler/php/php_generator.cc:613
google::protobuf::io::Printer::failed
bool failed() const
Definition: protobuf/src/google/protobuf/io/printer.h:289
io
indent_
int indent_
Definition: json_writer.cc:72
google::protobuf::io::Printer::Annotate
void Annotate(const char *varname, const std::string &file_name)
Definition: protobuf/src/google/protobuf/io/printer.h:223
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
google::protobuf::io::Printer::Annotate
void Annotate(const char *varname, const SomeDescriptor *descriptor)
Definition: protobuf/src/google/protobuf/io/printer.h:200
google::protobuf::io::Printer
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer.h:181
google::protobuf::io::AnnotationCollector::Annotation
std::pair< std::pair< size_t, size_t >, std::string > Annotation
Definition: protobuf/src/google/protobuf/io/printer.h:58
output_
std::string output_
Definition: json_writer.cc:76
key
const char * key
Definition: hpack_parser_table.cc:164
google::protobuf::io::AnnotationCollector
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer.h:54
google::protobuf::io::AnnotationCollector::~AnnotationCollector
virtual ~AnnotationCollector()
Definition: protobuf/src/google/protobuf/io/printer.h:70
end_offset
uint16_t end_offset
Definition: protobuf/src/google/protobuf/descriptor.cc:947
google::protobuf::io::AnnotationCollector::AddAnnotationNew
virtual void AddAnnotationNew(Annotation &)
Definition: protobuf/src/google/protobuf/io/printer.h:68
google::protobuf::io::ZeroCopyOutputStream
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h:183
google::protobuf::io::Printer::Print
void Print(const char *text, const Args &... args)
Definition: protobuf/src/google/protobuf/io/printer.h:251
google::protobuf::io::Printer::Annotate
void Annotate(const char *begin_varname, const char *end_varname, const std::string &file_name)
Definition: protobuf/src/google/protobuf/io/printer.h:231
google::protobuf::io::AnnotationProtoCollector::annotation_proto_
AnnotationProto *const annotation_proto_
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer.h:106
google::protobuf::io::AnnotationProtoCollector::AddAnnotationNew
void AddAnnotationNew(Annotation &a) override
Definition: protobuf/src/google/protobuf/io/printer.h:98
google::protobuf::io::AnnotationProtoCollector::AddAnnotation
void AddAnnotation(size_t begin_offset, size_t end_offset, const std::string &file_path, const std::vector< int > &path) override
Definition: protobuf/src/google/protobuf/io/printer.h:85
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:45