Line data Source code
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 : #include <google/protobuf/io/printer.h>
36 : #include <google/protobuf/io/zero_copy_stream.h>
37 : #include <google/protobuf/stubs/logging.h>
38 : #include <google/protobuf/stubs/common.h>
39 :
40 : namespace google {
41 : namespace protobuf {
42 : namespace io {
43 :
44 146 : Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
45 : : variable_delimiter_(variable_delimiter),
46 : output_(output),
47 : buffer_(NULL),
48 : buffer_size_(0),
49 : at_start_of_line_(true),
50 292 : failed_(false) {
51 146 : }
52 :
53 292 : Printer::~Printer() {
54 : // Only BackUp() if we have called Next() at least once and never failed.
55 146 : if (buffer_size_ > 0 && !failed_) {
56 140 : output_->BackUp(buffer_size_);
57 : }
58 146 : }
59 :
60 166866 : void Printer::Print(const map<string, string>& variables, const char* text) {
61 166866 : int size = strlen(text);
62 166866 : int pos = 0; // The number of bytes we've written so far.
63 :
64 9129024 : for (int i = 0; i < size; i++) {
65 8962158 : if (text[i] == '\n') {
66 : // Saw newline. If there is more text, we may need to insert an indent
67 : // here. So, write what we have so far, including the '\n'.
68 405447 : WriteRaw(text + pos, i - pos + 1);
69 405447 : pos = i + 1;
70 :
71 : // Setting this true will cause the next WriteRaw() to insert an indent
72 : // first.
73 405447 : at_start_of_line_ = true;
74 :
75 8556711 : } else if (text[i] == variable_delimiter_) {
76 : // Saw the start of a variable name.
77 :
78 : // Write what we have so far.
79 454761 : WriteRaw(text + pos, i - pos);
80 454761 : pos = i + 1;
81 :
82 : // Find closing delimiter.
83 909522 : const char* end = strchr(text + pos, variable_delimiter_);
84 454761 : if (end == NULL) {
85 0 : GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
86 0 : end = text + pos;
87 : }
88 454761 : int endpos = end - text;
89 :
90 454761 : string varname(text + pos, endpos - pos);
91 454761 : if (varname.empty()) {
92 : // Two delimiters in a row reduce to a literal delimiter character.
93 0 : WriteRaw(&variable_delimiter_, 1);
94 : } else {
95 : // Replace with the variable's value.
96 454761 : map<string, string>::const_iterator iter = variables.find(varname);
97 454761 : if (iter == variables.end()) {
98 0 : GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
99 : } else {
100 1364283 : WriteRaw(iter->second.data(), iter->second.size());
101 : }
102 : }
103 :
104 : // Advance past this variable.
105 454761 : i = endpos;
106 454761 : pos = endpos + 1;
107 : }
108 : }
109 :
110 : // Write the rest.
111 166866 : WriteRaw(text + pos, size - pos);
112 166866 : }
113 :
114 49541 : void Printer::Print(const char* text) {
115 49555 : static map<string, string> empty;
116 49541 : Print(empty, text);
117 49541 : }
118 :
119 43038 : void Printer::Print(const char* text,
120 : const char* variable, const string& value) {
121 : map<string, string> vars;
122 86076 : vars[variable] = value;
123 43038 : Print(vars, text);
124 43038 : }
125 :
126 8814 : void Printer::Print(const char* text,
127 : const char* variable1, const string& value1,
128 : const char* variable2, const string& value2) {
129 : map<string, string> vars;
130 17628 : vars[variable1] = value1;
131 17628 : vars[variable2] = value2;
132 8814 : Print(vars, text);
133 8814 : }
134 :
135 582 : void Printer::Print(const char* text,
136 : const char* variable1, const string& value1,
137 : const char* variable2, const string& value2,
138 : const char* variable3, const string& value3) {
139 : map<string, string> vars;
140 1164 : vars[variable1] = value1;
141 1164 : vars[variable2] = value2;
142 1164 : vars[variable3] = value3;
143 582 : Print(vars, text);
144 582 : }
145 :
146 397 : void Printer::Print(const char* text,
147 : const char* variable1, const string& value1,
148 : const char* variable2, const string& value2,
149 : const char* variable3, const string& value3,
150 : const char* variable4, const string& value4) {
151 : map<string, string> vars;
152 794 : vars[variable1] = value1;
153 794 : vars[variable2] = value2;
154 794 : vars[variable3] = value3;
155 794 : vars[variable4] = value4;
156 397 : Print(vars, text);
157 397 : }
158 :
159 0 : void Printer::Print(const char* text,
160 : const char* variable1, const string& value1,
161 : const char* variable2, const string& value2,
162 : const char* variable3, const string& value3,
163 : const char* variable4, const string& value4,
164 : const char* variable5, const string& value5) {
165 : map<string, string> vars;
166 0 : vars[variable1] = value1;
167 0 : vars[variable2] = value2;
168 0 : vars[variable3] = value3;
169 0 : vars[variable4] = value4;
170 0 : vars[variable5] = value5;
171 0 : Print(vars, text);
172 0 : }
173 :
174 0 : void Printer::Print(const char* text,
175 : const char* variable1, const string& value1,
176 : const char* variable2, const string& value2,
177 : const char* variable3, const string& value3,
178 : const char* variable4, const string& value4,
179 : const char* variable5, const string& value5,
180 : const char* variable6, const string& value6) {
181 : map<string, string> vars;
182 0 : vars[variable1] = value1;
183 0 : vars[variable2] = value2;
184 0 : vars[variable3] = value3;
185 0 : vars[variable4] = value4;
186 0 : vars[variable5] = value5;
187 0 : vars[variable6] = value6;
188 0 : Print(vars, text);
189 0 : }
190 :
191 0 : 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 : const char* variable5, const string& value5,
197 : const char* variable6, const string& value6,
198 : const char* variable7, const string& value7) {
199 : map<string, string> vars;
200 0 : vars[variable1] = value1;
201 0 : vars[variable2] = value2;
202 0 : vars[variable3] = value3;
203 0 : vars[variable4] = value4;
204 0 : vars[variable5] = value5;
205 0 : vars[variable6] = value6;
206 0 : vars[variable7] = value7;
207 0 : Print(vars, text);
208 0 : }
209 :
210 0 : void Printer::Print(const char* text,
211 : const char* variable1, const string& value1,
212 : const char* variable2, const string& value2,
213 : const char* variable3, const string& value3,
214 : const char* variable4, const string& value4,
215 : const char* variable5, const string& value5,
216 : const char* variable6, const string& value6,
217 : const char* variable7, const string& value7,
218 : const char* variable8, const string& value8) {
219 : map<string, string> vars;
220 0 : vars[variable1] = value1;
221 0 : vars[variable2] = value2;
222 0 : vars[variable3] = value3;
223 0 : vars[variable4] = value4;
224 0 : vars[variable5] = value5;
225 0 : vars[variable6] = value6;
226 0 : vars[variable7] = value7;
227 0 : vars[variable8] = value8;
228 0 : Print(vars, text);
229 0 : }
230 :
231 18832 : void Printer::Indent() {
232 18832 : indent_ += " ";
233 18832 : }
234 :
235 18832 : void Printer::Outdent() {
236 37664 : if (indent_.empty()) {
237 0 : GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
238 18832 : return;
239 : }
240 :
241 18832 : indent_.resize(indent_.size() - 2);
242 : }
243 :
244 0 : void Printer::PrintRaw(const string& data) {
245 0 : WriteRaw(data.data(), data.size());
246 0 : }
247 :
248 0 : void Printer::PrintRaw(const char* data) {
249 0 : if (failed_) return;
250 0 : WriteRaw(data, strlen(data));
251 : }
252 :
253 1858861 : void Printer::WriteRaw(const char* data, int size) {
254 1858861 : if (failed_) return;
255 1858861 : if (size == 0) return;
256 :
257 1349229 : if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
258 : // Insert an indent.
259 377026 : at_start_of_line_ = false;
260 754052 : WriteRaw(indent_.data(), indent_.size());
261 377026 : if (failed_) return;
262 : }
263 :
264 1350946 : while (size > buffer_size_) {
265 : // Data exceeds space in the buffer. Copy what we can and request a
266 : // new buffer.
267 1717 : memcpy(buffer_, data, buffer_size_);
268 1717 : data += buffer_size_;
269 1717 : size -= buffer_size_;
270 : void* void_buffer;
271 1717 : failed_ = !output_->Next(&void_buffer, &buffer_size_);
272 1717 : if (failed_) return;
273 1717 : buffer_ = reinterpret_cast<char*>(void_buffer);
274 : }
275 :
276 : // Buffer is big enough to receive the data; copy it.
277 1349229 : memcpy(buffer_, data, size);
278 1349229 : buffer_ += size;
279 1349229 : buffer_size_ -= size;
280 : }
281 :
282 : } // namespace io
283 : } // namespace protobuf
284 : } // namespace google
|