OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 // | |
5 // Author: markus@chromium.org | |
6 | |
7 #include <limits> | |
8 | |
9 #include "base/debug/format.h" | |
jln (very slow on Chromium)
2013/08/12 23:03:40
Please, have this as the first include as per styl
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
10 | |
11 #if !defined(NDEBUG) | |
12 // In debug builds, we use RAW_CHECK() to print useful error messages, if | |
13 // Format() is called with broken arguments. | |
14 // As our contract promises that Format() can be called from any restricted | |
15 // run-time context, it is not actually safe to call logging functions from it; | |
16 // and we only ever do so for debug builds and hope for the best. | |
17 // We should _never_ call any logging function other than RAW_CHECK(), and | |
18 // we should _never_ include any logging code that is active in production | |
19 // builds. Most notably, we should not include these logging functions in | |
20 // unofficial release builds, even though those builds would otherwise have | |
21 // DCHECKS() enabled. | |
22 // In other words; please do not remove the #ifdef around this #include. | |
23 // Instead, in production builds we opt for returning a degraded result, | |
24 // whenever an error is encountered. | |
25 // E.g. The broken function call | |
26 // Format("errno = %d (%x)", errno, strerror(errno)) | |
27 // will print something like | |
28 // errno = 13, (%x) | |
29 // instead of | |
30 // errno = 13 (Access denied) | |
31 // In most of the anticipated use cases, that's probably the preferred | |
32 // behavior. | |
33 #include "base/logging.h" | |
34 #define DEBUG_CHECK RAW_CHECK | |
35 #else | |
36 #define DEBUG_CHECK(x) do { if (x) { } } while (0) | |
37 #endif | |
38 | |
39 namespace base { | |
40 namespace debug { | |
41 | |
42 // The code in this file is extremely careful to be async-signal-safe. | |
43 // | |
44 // Most obviously, we avoid calling any code that could dynamically allocate | |
45 // memory. Doing so would almost certainly result in bugs and dead-locks. | |
46 // We also avoid calling any other STL functions that could have unintended | |
47 // side-effects involving memory allocation or access to other shared | |
48 // resources. | |
49 // | |
50 // But on top of that, we also avoid calling other library functions, as many | |
51 // of them have the side-effect of calling getenv() (in order to deal with | |
52 // localization) or accessing errno. The latter sounds benign, but there are | |
53 // several execution contexts where it isn't even possible to safely read let | |
54 // alone write errno. | |
55 // | |
56 // The stated design goal of the Format() function is that it can be called | |
57 // from any context that can safely call C or C++ code (i.e. anything that | |
58 // doesn't require assembly code). | |
59 // | |
60 // For a brief overview of some but not all of the issues with async-signal- | |
61 // safety, refer to: | |
62 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html | |
63 | |
64 namespace { | |
65 const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1; | |
66 | |
67 const char kUpCaseHexDigits[] = "0123456789ABCDEF"; | |
68 const char kDownCaseHexDigits[] = "0123456789abcdef"; | |
69 } | |
70 | |
71 #ifdef NDEBUG | |
jln (very slow on Chromium)
2013/08/12 22:20:50
#if defined(NDEBUG)
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
72 // We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), | |
73 // but C++ doesn't allow us to do that for constants. Instead, we have to | |
74 // use careful casting and shifting. We later use a COMPILE_ASSERT to | |
75 // verify that this worked correctly. | |
76 namespace { | |
77 const size_t kSSizeMax = kSSizeMaxConst; | |
78 } | |
79 #else | |
80 // For efficiency, we really need kSSizeMax to be a constant. But for unit | |
81 // tests, it should be adjustable. This allows us to verify edge cases without | |
82 // having to fill the entire available address space. As a compromise, we make | |
83 // kSSizeMax adjustable in debug builds, and then only compile that particular | |
84 // part of the unit test in debug builds. | |
85 namespace { | |
86 static size_t kSSizeMax = kSSizeMaxConst; | |
87 } | |
88 | |
89 namespace internal { | |
90 void SetFormatSSizeMax(size_t max) { | |
91 kSSizeMax = max; | |
92 } | |
93 | |
94 size_t GetFormatSSizeMax() { | |
95 return kSSizeMax; | |
96 } | |
97 } | |
98 #endif | |
jln (very slow on Chromium)
2013/08/12 22:20:50
// defined(NDEBUG)
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
99 | |
100 namespace { | |
101 class Buffer { | |
jln (very slow on Chromium)
2013/08/12 22:20:50
I'm happy for a non publicly visible class, in an
jln (very slow on Chromium)
2013/08/12 22:20:50
Nit: no indent in a namespace.
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
102 public: | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Nit: public is one space indent from "class Buffer
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
103 // |buffer| is caller-allocated storage that Format() writes to. It | |
104 // has |size| bytes of writable storage. | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Document clearly that size == 0 would lead to unde
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
105 Buffer(char* buffer, size_t size) | |
106 : buffer_(buffer), | |
107 size_(size - 1), // Account for trailing NUL byte | |
108 count_(0) { | |
109 // This test should work on all C++11 compilers, but apparently something is | |
110 // not working on all versions of clang just yet (e.g. on Mac, IOS, and | |
111 // Android). We are conservative and exclude all of clang for the time being. | |
112 // TODO(markus): Check if this restriction can be lifted. | |
113 #if __cplusplus >= 201103 && !defined(__clang__) | |
114 COMPILE_ASSERT(kSSizeMaxConst == std::numeric_limits<ssize_t>::max(), | |
115 kSSizeMax_is_the_max_value_of_an_ssize_t); | |
116 #endif | |
117 DEBUG_CHECK(size > 0); | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Just make it a real RAW_CHECK. If someone passes s
jln (very slow on Chromium)
2013/08/12 22:20:50
I would make this a real check.
Markus (顧孟勤)
2013/08/13 16:13:18
As discussed earlier, I don't want to change this.
| |
118 DEBUG_CHECK(size <= kSSizeMax); | |
119 } | |
120 | |
121 ~Buffer() { | |
122 // The caller guaranteed that there was enough space to store a trailing | |
jln (very slow on Chromium)
2013/08/12 22:20:50
The constructor guaranteed that...
| |
123 // NUL -- and in debug builds, we are actually verifying this with | |
124 // DEBUG_CHECK()s. So, we can always unconditionally write the NUL byte | |
125 // in the destructor. | |
126 // We do not need to adjust the count_, as Format() copies snprintf() in | |
127 // not including the NUL byte in its return code. | |
128 *GetInsertionPoint() = '\000'; | |
129 } | |
130 | |
131 // Returns true, iff the buffer is filled all the way to |kSSizeMax-1|. The | |
132 // caller can now stop adding more data, as GetCount() has reached its | |
133 // maximum possible value. | |
134 inline bool OutOfAddressableSpace() const { | |
135 return count_ == static_cast<size_t>(kSSizeMax - 1); | |
136 } | |
137 | |
138 // Return the number of bytes that have been emitted to |buffer_|. This | |
jln (very slow on Chromium)
2013/08/12 22:20:50
This comment reads as-if you had a buffer overflow
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
Let me know, if this makes more sense. It's
| |
139 // number can be larger than |size_|, if the caller provided an | |
140 // insufficiently large output buffer. But it will never be bigger than | |
141 // |kSSizeMax-1|. | |
142 inline ssize_t GetCount() const { | |
143 DEBUG_CHECK(count_ < kSSizeMax); | |
144 return static_cast<ssize_t>(count_); | |
145 } | |
146 | |
147 // Emits one |ch| character into the |buffer_| and updates the |count_| of | |
148 // characters that are currently supposed to be in the buffer. | |
149 // Returns "false", iff the buffer was already full. | |
150 // N.B. |count_| increases even if no characters have been written. This is | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Don't forget to explain how count_ work, where cou
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
151 // needed so that GetCount() can return the number of bytes that should | |
152 // have been allocated for the |buffer_|. | |
153 inline bool Out(char ch) { | |
154 if (size_ >= 1 && count_ < size_) { | |
155 buffer_[count_] = ch; | |
156 return IncrementCountByOne(); | |
157 } | |
158 // |count_| still needs to be updated, even if the buffer has been | |
159 // filled completely. This allows Format() to return the number of bytes | |
160 // that should have been emitted. | |
161 IncrementCountByOne(); | |
162 return false; | |
163 } | |
164 | |
165 // Inserts |padding|-|len| bytes worth of padding into the |buffer_|. | |
166 // |count_| will also be incremented by the number of bytes that were meant | |
167 // to be emitted. The |pad| character is typically either a ' ' space | |
168 // or a '0' zero, but other non-NUL values are legal. | |
169 // Returns "false", iff the the |buffer_| filled up (i.e. |count_| | |
170 // overflowed |size_|) at any time during padding. | |
171 inline bool Pad(char pad, size_t padding, size_t len) { | |
172 DEBUG_CHECK(pad); | |
173 DEBUG_CHECK(padding >= 0 && padding <= kSSizeMax); | |
174 DEBUG_CHECK(len >= 0 && len <= kSSizeMax); | |
175 for (; padding > len; --padding) | |
176 if (!Out(pad)) { | |
177 if (--padding) | |
178 IncrementCount(padding-len); | |
179 return false; | |
180 } | |
181 return true; | |
182 } | |
183 | |
184 // POSIX doesn't define any async-signal-safe function for converting | |
185 // an integer to ASCII. Define our own version. | |
186 // | |
187 // This also gives us the ability to make the function a little more | |
188 // powerful and have it deal with |padding|, with truncation, and with | |
189 // predicting the length of the untruncated output. | |
190 // | |
191 // IToASCII() converts an (optionally signed) integer to ASCII. Unlike | |
192 // similar functions in the standard C library, it never appends a NUL | |
193 // character. This is left for the caller to do. | |
194 // | |
195 // It supports bases 2 through 16. Only a |base| of 10 is allowed to have | |
196 // a |sign|. Otherwise, |i| is treated as unsigned. | |
197 // | |
198 // Padding can be done with either '0' zeros or ' ' spaces. | |
199 // | |
200 // Prepends a |prefix| to the number (e.g. "0x"). This prefix goes to | |
201 // the left of |padding|, if |pad| is '0'; and to the right of |padding| | |
202 // if |pad| is ' '. | |
203 // | |
204 // Returns "false", if the |buffer_| overflowed at any time. | |
205 bool IToASCII(bool sign, bool upcase, int64_t i, int base, | |
206 char pad, size_t padding, const char* prefix); | |
207 | |
208 private: | |
209 // Increments |count_| by |inc| unless this would cause |count_| to | |
210 // overflow |kSSizeMax-1|. Returns "false", iff an overflow was detected; | |
211 // it then clamps |count_| to |kSSizeMax-1|. | |
212 inline bool IncrementCount(size_t inc) { | |
213 // "inc" is either 1 or a "padding" value. Padding is clamped at | |
214 // run-time to at most kSSizeMax-1. So, we know that "inc" is always in | |
215 // the range 1..kSSizeMax-1. | |
216 // This allows us to compute "kSSizeMax - 1 - inc" without incurring any | |
217 // integer overflows. | |
218 DEBUG_CHECK(inc <= kSSizeMax - 1); | |
219 if (count_ > kSSizeMax - 1 - inc) { | |
220 count_ = kSSizeMax - 1; | |
221 return false; | |
222 } else { | |
223 count_ += inc; | |
224 return true; | |
225 } | |
226 } | |
227 | |
228 // Convenience method for the common case of incrementing |count_| by one. | |
229 inline bool IncrementCountByOne() { | |
230 return IncrementCount(1); | |
231 } | |
232 | |
233 // Return the current insertion point into the buffer. This is typically | |
jln (very slow on Chromium)
2013/08/12 22:49:40
Please, define "insertion point" better.
Markus (顧孟勤)
2013/08/13 16:13:18
Let me know if this is easier to understand.
| |
234 // at |buffer_| + |count_|, but could be before that if truncation | |
235 // happened. | |
236 inline char* GetInsertionPoint() const { | |
237 size_t idx = count_; | |
238 if (idx > size_) | |
239 idx = size_; | |
240 return buffer_ + idx; | |
241 } | |
242 | |
243 char* buffer_; | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Add comments here. It's really important to explai
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
244 const size_t size_; | |
245 size_t count_; | |
246 }; | |
jln (very slow on Chromium)
2013/08/12 22:20:50
DISALLOW_COPY_AND_ASSIGN()
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
247 | |
248 | |
jln (very slow on Chromium)
2013/08/12 22:20:50
Add some documentation, especially say what |i| is
Markus (顧孟勤)
2013/08/13 16:13:18
All of that is documented inside of the class decl
| |
249 bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base, | |
250 char pad, size_t padding, const char* prefix) { | |
251 // Sanity check for parameters. None of these should ever fail, but see | |
252 // above for the rationale why we can't call CHECK(). | |
253 DEBUG_CHECK(base >= 2); | |
254 DEBUG_CHECK(base <= 16); | |
255 DEBUG_CHECK(!sign || base == 10); | |
256 DEBUG_CHECK(pad == '0' || pad == ' '); | |
257 DEBUG_CHECK(padding >= 0); | |
258 DEBUG_CHECK(padding <= kSSizeMax); | |
259 DEBUG_CHECK(!(sign && prefix && *prefix)); | |
260 | |
261 // Handle negative numbers, if requested by caller. | |
262 int minint = 0; | |
263 uint64_t num; | |
264 if (sign && i < 0) { | |
265 prefix = "-"; | |
266 | |
267 // Turn our number positive. | |
268 if (i == std::numeric_limits<int64_t>::min()) { | |
jln (very slow on Chromium)
2013/08/12 22:20:50
typeof(i) instead of int64_t ?
Markus (顧孟勤)
2013/08/13 16:13:18
typeof() isn't part of the C++ standard -- unfortu
| |
269 // The most negative integer needs special treatment. | |
270 minint = 1; | |
271 num = -(i + 1); | |
272 } else { | |
273 // "Normal" negative numbers are easy. | |
274 num = -i; | |
275 } | |
276 } else | |
jln (very slow on Chromium)
2013/08/12 22:20:50
style: add {}
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
In fact, I added all braces back, since you
| |
277 num = i; | |
jln (very slow on Chromium)
2013/08/12 22:20:50
This is doing some dark magic. This has to be:
1.
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
278 | |
279 // If padding with '0' zero, emit the prefix or '-' character now. Otherwise, | |
280 // make the prefix accessible in reverse order, so that we can later output | |
281 // it right between padding and the number. | |
282 // We cannot choose the easier approach of just reversing the number, as that | |
283 // fails in situations where we need to truncate numbers that have padding | |
284 // and/or prefixes. | |
285 const char* reverse_prefix = NULL; | |
286 if (prefix && *prefix) { | |
287 if (pad == '0') { | |
288 while (*prefix) { | |
289 if (padding) | |
290 --padding; | |
291 Out(*prefix++); | |
292 } | |
293 prefix = NULL; | |
294 } else { | |
295 for (reverse_prefix = prefix; *reverse_prefix; ++reverse_prefix) { | |
296 } | |
297 } | |
298 } else | |
jln (very slow on Chromium)
2013/08/12 22:20:50
style: add {}
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
299 prefix = NULL; | |
300 const size_t prefix_length = reverse_prefix - prefix; | |
301 | |
302 // Loop until we have converted the entire number. Output at least one | |
303 // character (i.e. '0'). | |
304 size_t start = count_; | |
305 size_t discarded = 0; | |
306 bool started = false; | |
307 do { | |
308 // Make sure there is still enough space left in our output buffer. | |
309 if (count_ >= size_) { | |
310 if (start < size_) { | |
311 // It is rare that we need to output a partial number. But if asked | |
312 // to do so, we will still make sure we output the correct number of | |
313 // leading digits. | |
314 // Since we are generating the digits in reverse order, we actually | |
315 // have to discard digits in the order that we have already emitted | |
316 // them. This is essentially equivalent to: | |
317 // memmove(buffer_ + start, buffer_ + start + 1, size_ - start - 1) | |
318 for (char* move = buffer_ + start, *end = buffer_ + size_ - 1; | |
319 move < end; | |
320 ++move) | |
321 *move = move[1]; | |
322 ++discarded; | |
323 --count_; | |
324 } else if (count_ - size_ > 1) { | |
325 // Need to increment either |count_| or |discarded| to make progress. | |
326 // The latter is more efficient, as it eventually triggers fast | |
327 // handling of padding. But we have to ensure we don't accidentally | |
328 // change the overall state (i.e. switch the state-machine from | |
329 // discarding to non-discarding). |count_| needs to always stay | |
330 // bigger than |size_|. | |
331 --count_; | |
332 ++discarded; | |
333 } | |
334 } | |
335 | |
336 // Output the next digit and (if necessary) compensate for the most | |
337 // negative integer needing special treatment. This works because, | |
338 // no matter the bit width of the integer, the lowest-most decimal | |
339 // integer always ends in 2, 4, 6, or 8. | |
340 if (!num && started) | |
jln (very slow on Chromium)
2013/08/12 22:49:40
Nit: braces are mandatory for multi-line if statem
Markus (顧孟勤)
2013/08/13 16:13:18
Done.
| |
341 if (reverse_prefix > prefix) | |
342 Out(*--reverse_prefix); | |
343 else | |
344 Out(pad); | |
345 else { | |
346 started = true; | |
347 Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]); | |
348 } | |
349 | |
350 minint = 0; | |
351 num /= base; | |
352 | |
353 // Add padding, if requested. | |
354 if (padding > 0) { | |
355 --padding; | |
356 | |
357 // Performance optimization for when we are asked to output | |
358 // excessive padding, but our output buffer is limited in size. | |
359 // Even if we output a 128bit number in binary, we would never | |
360 // write more than 128 plus prefix non-padding characters. So, anything | |
361 // beyond this limit and we can compute the result arithmetically, as | |
jln (very slow on Chromium)
2013/08/12 22:49:40
You forgot a verb in the first proposition of this
Markus (顧孟勤)
2013/08/13 16:13:18
I had trouble wording this comment. Let me know if
| |
362 // we know that our entire output consists of padding characters that | |
363 // have already been outputted. | |
364 if (discarded > 128 + prefix_length) { | |
365 IncrementCount(padding); | |
366 padding = 0; | |
367 } | |
368 } | |
369 } while (num || padding || (reverse_prefix > prefix)); | |
370 | |
371 // Conversion to ASCII actually resulted in the digits being in reverse | |
372 // order. We can't easily generate them in forward order, as we can't tell | |
373 // the number of characters needed until we are done converting. | |
374 // So, now, we reverse the string (except for the possible '-' sign). | |
375 char* front = buffer_ + start; | |
376 char* back = GetInsertionPoint(); | |
377 while (--back > front) { | |
378 char ch = *back; | |
379 *back = *front; | |
380 *front++ = ch; | |
381 } | |
382 | |
383 IncrementCount(discarded); | |
384 return !discarded; | |
385 } | |
386 | |
387 } // anonymous namespace | |
388 | |
389 ssize_t internal::FormatN(char* buf, size_t sz, const char* fmt, | |
390 const Arg* args, const size_t max_args) { | |
391 // Make sure that at least one NUL byte can be written, and that the buffer | |
392 // never overflows kSSizeMax. Not only does that use up most or all of the | |
393 // address space, it also would result in a return code that cannot be | |
394 // represented. | |
395 if (static_cast<ssize_t>(sz) < 1) | |
396 return -1; | |
397 else if (sz > kSSizeMax) { | |
398 sz = kSSizeMax; | |
399 } | |
400 | |
401 // Iterate over format string and interpret '%' arguments as they are | |
402 // encountered. | |
403 Buffer buffer(buf, sz); | |
404 size_t padding; | |
405 char pad; | |
406 for (unsigned int cur_arg = 0; *fmt && !buffer.OutOfAddressableSpace(); ) { | |
407 if (*fmt++ == '%') { | |
408 padding = 0; | |
409 pad = ' '; | |
410 char ch = *fmt++; | |
411 format_character_found: | |
412 switch (ch) { | |
413 case '0': case '1': case '2': case '3': case '4': | |
414 case '5': case '6': case '7': case '8': case '9': | |
415 // Found a width parameter. Convert to an integer value and store in | |
416 // "padding". If the leading digit is a zero, change the padding | |
417 // character from a space ' ' to a zero '0'. | |
418 pad = ch == '0' ? '0' : ' '; | |
419 for (;;) { | |
420 // The maximum allowed padding fills all the available address | |
421 // space and leaves just enough space to insert the trailing NUL. | |
422 const size_t max_padding = kSSizeMax - 1; | |
423 if (padding > max_padding/10 || | |
424 10*padding > max_padding - (ch - '0')) { | |
425 DEBUG_CHECK(padding <= max_padding/10 && | |
426 10*padding <= max_padding - (ch - '0')); | |
427 // Integer overflow detected. Skip the rest of the width until | |
428 // we find the format character, then do the normal error handling. | |
429 while ((ch = *fmt++) >= '0' && ch <= '9') { | |
430 } | |
431 goto fail_to_expand; | |
432 } | |
433 padding = 10*padding + ch - '0'; | |
434 ch = *fmt++; | |
435 if (ch < '0' || ch > '9') { | |
436 // Reached the end of the width parameter. This is where the format | |
437 // character is found. | |
438 goto format_character_found; | |
439 } | |
440 } | |
441 break; | |
442 case 'c': { // Output an ASCII character. | |
443 // Check that there are arguments left to be inserted. | |
444 if (cur_arg >= max_args) { | |
445 DEBUG_CHECK(cur_arg < max_args); | |
446 goto fail_to_expand; | |
447 } | |
448 | |
449 // Check that the argument has the expected type. | |
450 const Arg& arg = args[cur_arg++]; | |
451 if (arg.type_ != Arg::INT && | |
452 arg.type_ != Arg::UINT) { | |
453 DEBUG_CHECK(arg.type_ == Arg::INT || | |
454 arg.type_ == Arg::UINT); | |
455 goto fail_to_expand; | |
456 } | |
457 | |
458 // Apply padding, if needed. | |
459 buffer.Pad(' ', padding, 1); | |
460 | |
461 // Convert the argument to an ASCII character and output it. | |
462 char ch = static_cast<char>(arg.i_); | |
463 if (!ch) | |
464 goto end_of_output_buffer; | |
465 buffer.Out(ch); | |
466 break; } | |
467 case 'd': // Output a possibly signed decimal value. | |
468 case 'o': // Output an unsigned octal value. | |
469 case 'x': // Output an unsigned hexadecimal value. | |
470 case 'X': | |
471 case 'p': { // Output a pointer value. | |
472 // Check that there are arguments left to be inserted. | |
473 if (cur_arg >= max_args) { | |
474 DEBUG_CHECK(cur_arg < max_args); | |
475 goto fail_to_expand; | |
476 } | |
477 | |
478 const Arg& arg = args[cur_arg++]; | |
479 int64_t i; | |
480 const char* prefix = NULL; | |
481 if (ch != 'p') { | |
482 // Check that the argument has the expected type. | |
483 if (arg.type_ != Arg::INT && | |
484 arg.type_ != Arg::UINT) { | |
485 DEBUG_CHECK(arg.type_ == Arg::INT || | |
486 arg.type_ == Arg::UINT); | |
487 goto fail_to_expand; | |
488 } | |
489 i = arg.i_; | |
490 | |
491 if (ch != 'd') { | |
492 // The Arg() constructor automatically performed sign expansion on | |
493 // signed parameters. This is great when outputting a %d decimal | |
494 // number, but can result in unexpected leading 0xFF bytes when | |
495 // outputting a %x hexadecimal number. Mask bits, if necessary. | |
496 // We have to do this here, instead of in the Arg() constructor, as | |
497 // the Arg() constructor cannot tell whether we will output a %d | |
498 // or a %x. Only the latter should experience masking. | |
499 if (arg.width_ < sizeof(int64_t)) | |
500 i &= (1LL << (8*arg.width_)) - 1; | |
501 } | |
502 } else { | |
503 // Pointer values require an actual pointer or a string. | |
504 if (arg.type_ == Arg::POINTER) | |
505 i = reinterpret_cast<uintptr_t>(arg.ptr_); | |
506 else if (arg.type_ == Arg::STRING) | |
507 i = reinterpret_cast<uintptr_t>(arg.s_); | |
508 else if (arg.type_ == Arg::INT && arg.width_ == sizeof(void *) && | |
509 arg.i_ == 0) // Allow C++'s version of NULL | |
510 i = 0; | |
511 else { | |
512 DEBUG_CHECK(arg.type_ == Arg::POINTER || | |
513 arg.type_ == Arg::STRING); | |
514 goto fail_to_expand; | |
515 } | |
516 | |
517 // Pointers always include the "0x" prefix. | |
518 prefix = "0x"; | |
519 } | |
520 | |
521 // Use IToASCII() to convert to ASCII representation. For decimal | |
522 // numbers, optionally print a sign. For hexadecimal numbers, | |
523 // distinguish between upper and lower case. %p addresses are always | |
524 // printed as upcase. Supports base 8, 10, and 16. Prints padding | |
525 // and/or prefixes, if so requested. | |
526 buffer.IToASCII(ch == 'd' && arg.type_ == Arg::INT, | |
527 ch != 'x', i, | |
528 ch == 'o' ? 8 : ch == 'd' ? 10 : 16, | |
529 pad, padding, prefix); | |
530 break; } | |
531 case 's': { | |
532 // Check that there are arguments left to be inserted. | |
533 if (cur_arg >= max_args) { | |
534 DEBUG_CHECK(cur_arg < max_args); | |
535 goto fail_to_expand; | |
536 } | |
537 | |
538 // Check that the argument has the expected type. | |
539 const Arg& arg = args[cur_arg++]; | |
540 const char *s; | |
541 if (arg.type_ == Arg::STRING) | |
542 s = arg.s_ ? arg.s_ : "<NULL>"; | |
543 else if (arg.type_ == Arg::INT && arg.width_ == sizeof(void *) && | |
544 arg.i_ == 0) // Allow C++'s version of NULL | |
545 s = "<NULL>"; | |
546 else { | |
547 DEBUG_CHECK(arg.type_ == Arg::STRING); | |
548 goto fail_to_expand; | |
549 } | |
550 | |
551 // Apply padding, if needed. This requires us to first check the | |
552 // length of the string that we are outputting. | |
553 if (padding) { | |
554 size_t len = 0; | |
555 for (const char* src = s; *src++; ) | |
556 ++len; | |
557 buffer.Pad(' ', padding, len); | |
558 } | |
559 | |
560 // Printing a string involves nothing more than copying it into the | |
561 // output buffer and making sure we don't output more bytes than | |
562 // available space; Out() takes care of doing that. | |
563 for (const char* src = s; *src; ) | |
564 buffer.Out(*src++); | |
565 break; } | |
566 case '%': | |
567 // Quoted percent '%' character. | |
568 goto copy_verbatim; | |
569 fail_to_expand: | |
570 // C++ gives us tools to do type checking -- something that snprintf() | |
571 // could never really do. So, whenever we see arguments that don't | |
572 // match up with the format string, we refuse to output them. But | |
573 // since we have to be extremely conservative about being async- | |
574 // signal-safe, we are limited in the type of error handling that we | |
575 // can do in production builds (in debug builds we can use | |
576 // DEBUG_CHECK() and hope for the best). So, all we do is pass the | |
577 // format string unchanged. That should eventually get the user's | |
578 // attention; and in the meantime, it hopefully doesn't lose too much | |
579 // data. | |
580 default: | |
581 // Unknown or unsupported format character. Just copy verbatim to | |
582 // output. | |
583 buffer.Out('%'); | |
584 DEBUG_CHECK(ch); | |
585 if (!ch) | |
586 goto end_of_format_string; | |
587 buffer.Out(ch); | |
588 break; | |
589 } | |
590 } else { | |
591 copy_verbatim: | |
592 buffer.Out(fmt[-1]); | |
593 } | |
594 } | |
595 end_of_format_string: | |
596 end_of_output_buffer: | |
597 return buffer.GetCount(); | |
598 } | |
599 | |
600 ssize_t FormatN(char* buf, size_t sz, const char* fmt) { | |
601 // Make sure that at least one NUL byte can be written, and that the buffer | |
602 // never overflows kSSizeMax. Not only does that use up most or all of the | |
603 // address space, it also would result in a return code that cannot be | |
604 // represented. | |
605 if (static_cast<ssize_t>(sz) < 1) | |
606 return -1; | |
607 else if (sz > kSSizeMax) { | |
608 sz = kSSizeMax; | |
609 } | |
610 | |
611 Buffer buffer(buf, sz); | |
612 | |
613 // In the slow-path, we deal with errors by copying the contents of | |
614 // "fmt" unexpanded. This means, if there are no arguments passed, the | |
615 // Format() function always degenerates to a version of strncpy() that | |
616 // de-duplicates '%' characters. | |
617 const char* src = fmt; | |
618 for (; *src; ++src) { | |
619 buffer.Out(*src); | |
620 DEBUG_CHECK(src[0] != '%' || src[1] == '%'); | |
621 if (src[0] == '%' && src[1] == '%') | |
622 ++src; | |
623 } | |
624 return buffer.GetCount(); | |
625 } | |
626 | |
627 } // namespace debug | |
628 } // namespace base | |
OLD | NEW |