printer.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. #include <google/protobuf/io/printer.h>
  34. #include <google/protobuf/io/zero_copy_stream.h>
  35. #include <google/protobuf/stubs/logging.h>
  36. #include <google/protobuf/stubs/common.h>
  37. namespace google {
  38. namespace protobuf {
  39. namespace io {
  40. Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
  41. : variable_delimiter_(variable_delimiter),
  42. output_(output),
  43. buffer_(NULL),
  44. buffer_size_(0),
  45. offset_(0),
  46. at_start_of_line_(true),
  47. failed_(false),
  48. annotation_collector_(NULL) {}
  49. Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
  50. AnnotationCollector* annotation_collector)
  51. : variable_delimiter_(variable_delimiter),
  52. output_(output),
  53. buffer_(NULL),
  54. buffer_size_(0),
  55. offset_(0),
  56. at_start_of_line_(true),
  57. failed_(false),
  58. annotation_collector_(annotation_collector) {}
  59. Printer::~Printer() {
  60. // Only BackUp() if we have called Next() at least once and never failed.
  61. if (buffer_size_ > 0 && !failed_) {
  62. output_->BackUp(buffer_size_);
  63. }
  64. }
  65. bool Printer::GetSubstitutionRange(const char* varname,
  66. std::pair<size_t, size_t>* range) {
  67. std::map<string, std::pair<size_t, size_t> >::const_iterator iter =
  68. substitutions_.find(varname);
  69. if (iter == substitutions_.end()) {
  70. GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
  71. return false;
  72. }
  73. if (iter->second.first > iter->second.second) {
  74. GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
  75. << varname;
  76. return false;
  77. }
  78. *range = iter->second;
  79. return true;
  80. }
  81. void Printer::Annotate(const char* begin_varname, const char* end_varname,
  82. const string& file_path, const std::vector<int>& path) {
  83. if (annotation_collector_ == NULL) {
  84. // Can't generate signatures with this Printer.
  85. return;
  86. }
  87. std::pair<size_t, size_t> begin, end;
  88. if (!GetSubstitutionRange(begin_varname, &begin) ||
  89. !GetSubstitutionRange(end_varname, &end)) {
  90. return;
  91. }
  92. if (begin.first > end.second) {
  93. GOOGLE_LOG(DFATAL) << " Annotation has negative length from " << begin_varname
  94. << " to " << end_varname;
  95. } else {
  96. annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
  97. path);
  98. }
  99. }
  100. void Printer::Print(const std::map<string, string>& variables,
  101. const char* text) {
  102. int size = strlen(text);
  103. int pos = 0; // The number of bytes we've written so far.
  104. substitutions_.clear();
  105. line_start_variables_.clear();
  106. for (int i = 0; i < size; i++) {
  107. if (text[i] == '\n') {
  108. // Saw newline. If there is more text, we may need to insert an indent
  109. // here. So, write what we have so far, including the '\n'.
  110. WriteRaw(text + pos, i - pos + 1);
  111. pos = i + 1;
  112. // Setting this true will cause the next WriteRaw() to insert an indent
  113. // first.
  114. at_start_of_line_ = true;
  115. line_start_variables_.clear();
  116. } else if (text[i] == variable_delimiter_) {
  117. // Saw the start of a variable name.
  118. // Write what we have so far.
  119. WriteRaw(text + pos, i - pos);
  120. pos = i + 1;
  121. // Find closing delimiter.
  122. const char* end = strchr(text + pos, variable_delimiter_);
  123. if (end == NULL) {
  124. GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
  125. end = text + pos;
  126. }
  127. int endpos = end - text;
  128. string varname(text + pos, endpos - pos);
  129. if (varname.empty()) {
  130. // Two delimiters in a row reduce to a literal delimiter character.
  131. WriteRaw(&variable_delimiter_, 1);
  132. } else {
  133. // Replace with the variable's value.
  134. std::map<string, string>::const_iterator iter = variables.find(varname);
  135. if (iter == variables.end()) {
  136. GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
  137. } else {
  138. if (at_start_of_line_ && iter->second.empty()) {
  139. line_start_variables_.push_back(varname);
  140. }
  141. WriteRaw(iter->second.data(), iter->second.size());
  142. std::pair<std::map<string, std::pair<size_t, size_t> >::iterator,
  143. bool>
  144. inserted = substitutions_.insert(std::make_pair(
  145. varname,
  146. std::make_pair(offset_ - iter->second.size(), offset_)));
  147. if (!inserted.second) {
  148. // This variable was used multiple times. Make its span have
  149. // negative length so we can detect it if it gets used in an
  150. // annotation.
  151. inserted.first->second = std::make_pair(1, 0);
  152. }
  153. }
  154. }
  155. // Advance past this variable.
  156. i = endpos;
  157. pos = endpos + 1;
  158. }
  159. }
  160. // Write the rest.
  161. WriteRaw(text + pos, size - pos);
  162. }
  163. void Printer::Print(const char* text) {
  164. static std::map<string, string> empty;
  165. Print(empty, text);
  166. }
  167. void Printer::Print(const char* text,
  168. const char* variable, const string& value) {
  169. std::map<string, string> vars;
  170. vars[variable] = value;
  171. Print(vars, text);
  172. }
  173. void Printer::Print(const char* text,
  174. const char* variable1, const string& value1,
  175. const char* variable2, const string& value2) {
  176. std::map<string, string> vars;
  177. vars[variable1] = value1;
  178. vars[variable2] = value2;
  179. Print(vars, text);
  180. }
  181. void Printer::Print(const char* text,
  182. const char* variable1, const string& value1,
  183. const char* variable2, const string& value2,
  184. const char* variable3, const string& value3) {
  185. std::map<string, string> vars;
  186. vars[variable1] = value1;
  187. vars[variable2] = value2;
  188. vars[variable3] = value3;
  189. Print(vars, text);
  190. }
  191. void Printer::Print(const char* text,
  192. const char* variable1, const string& value1,
  193. const char* variable2, const string& value2,
  194. const char* variable3, const string& value3,
  195. const char* variable4, const string& value4) {
  196. std::map<string, string> vars;
  197. vars[variable1] = value1;
  198. vars[variable2] = value2;
  199. vars[variable3] = value3;
  200. vars[variable4] = value4;
  201. Print(vars, text);
  202. }
  203. void Printer::Print(const char* text,
  204. const char* variable1, const string& value1,
  205. const char* variable2, const string& value2,
  206. const char* variable3, const string& value3,
  207. const char* variable4, const string& value4,
  208. const char* variable5, const string& value5) {
  209. std::map<string, string> vars;
  210. vars[variable1] = value1;
  211. vars[variable2] = value2;
  212. vars[variable3] = value3;
  213. vars[variable4] = value4;
  214. vars[variable5] = value5;
  215. Print(vars, text);
  216. }
  217. void Printer::Print(const char* text,
  218. const char* variable1, const string& value1,
  219. const char* variable2, const string& value2,
  220. const char* variable3, const string& value3,
  221. const char* variable4, const string& value4,
  222. const char* variable5, const string& value5,
  223. const char* variable6, const string& value6) {
  224. std::map<string, string> vars;
  225. vars[variable1] = value1;
  226. vars[variable2] = value2;
  227. vars[variable3] = value3;
  228. vars[variable4] = value4;
  229. vars[variable5] = value5;
  230. vars[variable6] = value6;
  231. Print(vars, text);
  232. }
  233. void Printer::Print(const char* text,
  234. const char* variable1, const string& value1,
  235. const char* variable2, const string& value2,
  236. const char* variable3, const string& value3,
  237. const char* variable4, const string& value4,
  238. const char* variable5, const string& value5,
  239. const char* variable6, const string& value6,
  240. const char* variable7, const string& value7) {
  241. std::map<string, string> vars;
  242. vars[variable1] = value1;
  243. vars[variable2] = value2;
  244. vars[variable3] = value3;
  245. vars[variable4] = value4;
  246. vars[variable5] = value5;
  247. vars[variable6] = value6;
  248. vars[variable7] = value7;
  249. Print(vars, text);
  250. }
  251. void Printer::Print(const char* text,
  252. const char* variable1, const string& value1,
  253. const char* variable2, const string& value2,
  254. const char* variable3, const string& value3,
  255. const char* variable4, const string& value4,
  256. const char* variable5, const string& value5,
  257. const char* variable6, const string& value6,
  258. const char* variable7, const string& value7,
  259. const char* variable8, const string& value8) {
  260. std::map<string, string> vars;
  261. vars[variable1] = value1;
  262. vars[variable2] = value2;
  263. vars[variable3] = value3;
  264. vars[variable4] = value4;
  265. vars[variable5] = value5;
  266. vars[variable6] = value6;
  267. vars[variable7] = value7;
  268. vars[variable8] = value8;
  269. Print(vars, text);
  270. }
  271. void Printer::Indent() {
  272. indent_ += " ";
  273. }
  274. void Printer::Outdent() {
  275. if (indent_.empty()) {
  276. GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
  277. return;
  278. }
  279. indent_.resize(indent_.size() - 2);
  280. }
  281. void Printer::PrintRaw(const string& data) {
  282. WriteRaw(data.data(), data.size());
  283. }
  284. void Printer::PrintRaw(const char* data) {
  285. if (failed_) return;
  286. WriteRaw(data, strlen(data));
  287. }
  288. void Printer::WriteRaw(const char* data, int size) {
  289. if (failed_) return;
  290. if (size == 0) return;
  291. if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
  292. // Insert an indent.
  293. at_start_of_line_ = false;
  294. CopyToBuffer(indent_.data(), indent_.size());
  295. if (failed_) return;
  296. // Fix up empty variables (e.g., "{") that should be annotated as
  297. // coming after the indent.
  298. for (std::vector<string>::iterator i = line_start_variables_.begin();
  299. i != line_start_variables_.end(); ++i) {
  300. substitutions_[*i].first += indent_.size();
  301. substitutions_[*i].second += indent_.size();
  302. }
  303. }
  304. // If we're going to write any data, clear line_start_variables_, since
  305. // we've either updated them in the block above or they no longer refer to
  306. // the current line.
  307. line_start_variables_.clear();
  308. CopyToBuffer(data, size);
  309. }
  310. void Printer::CopyToBuffer(const char* data, int size) {
  311. if (failed_) return;
  312. if (size == 0) return;
  313. while (size > buffer_size_) {
  314. // Data exceeds space in the buffer. Copy what we can and request a
  315. // new buffer.
  316. if (buffer_size_ > 0) {
  317. memcpy(buffer_, data, buffer_size_);
  318. offset_ += buffer_size_;
  319. data += buffer_size_;
  320. size -= buffer_size_;
  321. }
  322. void* void_buffer;
  323. failed_ = !output_->Next(&void_buffer, &buffer_size_);
  324. if (failed_) return;
  325. buffer_ = reinterpret_cast<char*>(void_buffer);
  326. }
  327. // Buffer is big enough to receive the data; copy it.
  328. memcpy(buffer_, data, size);
  329. buffer_ += size;
  330. buffer_size_ -= size;
  331. offset_ += size;
  332. }
  333. } // namespace io
  334. } // namespace protobuf
  335. } // namespace google