You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

printer.h 20 kB

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