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


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:57