158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file.
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/safe_sprintf.h"
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <limits>
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if !defined(NDEBUG)
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// In debug builds, we use RAW_CHECK() to print useful error messages, if
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// SafeSPrintf() is called with broken arguments.
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// As our contract promises that SafeSPrintf() can be called from any
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// restricted run-time context, it is not actually safe to call logging
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// functions from it; and we only ever do so for debug builds and hope for the
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// best. We should _never_ call any logging function other than RAW_CHECK(),
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// and we should _never_ include any logging code that is active in production
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// builds. Most notably, we should not include these logging functions in
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// unofficial release builds, even though those builds would otherwise have
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// DCHECKS() enabled.
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// In other words; please do not remove the #ifdef around this #include.
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Instead, in production builds we opt for returning a degraded result,
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// whenever an error is encountered.
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// E.g. The broken function call
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//        SafeSPrintf("errno = %d (%x)", errno, strerror(errno))
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//      will print something like
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//        errno = 13, (%x)
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//      instead of
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//        errno = 13 (Access denied)
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//      In most of the anticipated use cases, that's probably the preferred
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//      behavior.
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/logging.h"
3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define DEBUG_CHECK RAW_CHECK
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define DEBUG_CHECK(x) do { if (x) { } } while (0)
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace base {
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace strings {
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The code in this file is extremely careful to be async-signal-safe.
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Most obviously, we avoid calling any code that could dynamically allocate
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// memory. Doing so would almost certainly result in bugs and dead-locks.
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// We also avoid calling any other STL functions that could have unintended
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// side-effects involving memory allocation or access to other shared
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// resources.
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// But on top of that, we also avoid calling other library functions, as many
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// of them have the side-effect of calling getenv() (in order to deal with
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// localization) or accessing errno. The latter sounds benign, but there are
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// several execution contexts where it isn't even possible to safely read let
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// alone write errno.
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The stated design goal of the SafeSPrintf() function is that it can be
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// called from any context that can safely call C or C++ code (i.e. anything
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// that doesn't require assembly code).
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// For a brief overview of some but not all of the issues with async-signal-
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// safety, refer to:
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1;
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kUpCaseHexDigits[]   = "0123456789ABCDEF";
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char kDownCaseHexDigits[] = "0123456789abcdef";
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(NDEBUG)
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(),
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// but C++ doesn't allow us to do that for constants. Instead, we have to
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// use careful casting and shifting. We later use a COMPILE_ASSERT to
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// verify that this worked correctly.
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const size_t kSSizeMax = kSSizeMaxConst;
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#else  // defined(NDEBUG)
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// For efficiency, we really need kSSizeMax to be a constant. But for unit
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// tests, it should be adjustable. This allows us to verify edge cases without
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// having to fill the entire available address space. As a compromise, we make
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// kSSizeMax adjustable in debug builds, and then only compile that particular
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// part of the unit test in debug builds.
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static size_t kSSizeMax = kSSizeMaxConst;
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace internal {
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SetSafeSPrintfSSizeMaxForTest(size_t max) {
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  kSSizeMax = max;
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)size_t GetSafeSPrintfSSizeMaxForTest() {
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return kSSizeMax;
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif  // defined(NDEBUG)
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class Buffer {
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |buffer| is caller-allocated storage that SafeSPrintf() writes to. It
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // has |size| bytes of writable storage. It is the caller's responsibility
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // to ensure that the buffer is at least one byte in size, so that it fits
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the trailing NUL that will be added by the destructor. The buffer also
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // must be smaller or equal to kSSizeMax in size.
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Buffer(char* buffer, size_t size)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      : buffer_(buffer),
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        size_(size - 1),  // Account for trailing NUL byte
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        count_(0) {
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The following assertion does not build on Mac and Android. This is because
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// static_assert only works with compile-time constants, but mac uses
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// libstdc++4.2 and android uses stlport, which both don't mark
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// numeric_limits::max() as constexp.  Likewise, MSVS2013's standard library
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// also doesn't mark max() as constexpr yet. cl.exe supports static_cast but
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// doesn't really implement constexpr yet so it doesn't complain, but clang
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// does.
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if __cplusplus >= 201103 && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    !defined(OS_IOS) && !(defined(__clang__) && defined(OS_WIN))
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    COMPILE_ASSERT(kSSizeMaxConst == \
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   static_cast<size_t>(std::numeric_limits<ssize_t>::max()),
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   kSSizeMax_is_the_max_value_of_an_ssize_t);
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(size > 0);
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(size <= kSSizeMax);
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ~Buffer() {
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // The code calling the constructor guaranteed that there was enough space
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // to store a trailing NUL -- and in debug builds, we are actually
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // verifying this with DEBUG_CHECK()s in the constructor. So, we can
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // always unconditionally write the NUL byte in the destructor.  We do not
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // need to adjust the count_, as SafeSPrintf() copies snprintf() in not
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // including the NUL byte in its return code.
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    *GetInsertionPoint() = '\000';
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns true, iff the buffer is filled all the way to |kSSizeMax-1|. The
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // caller can now stop adding more data, as GetCount() has reached its
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // maximum possible value.
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline bool OutOfAddressableSpace() const {
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return count_ == static_cast<size_t>(kSSizeMax - 1);
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns the number of bytes that would have been emitted to |buffer_|
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // if it was sized sufficiently large. This number can be larger than
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |size_|, if the caller provided an insufficiently large output buffer.
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // But it will never be bigger than |kSSizeMax-1|.
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline ssize_t GetCount() const {
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(count_ < kSSizeMax);
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return static_cast<ssize_t>(count_);
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Emits one |ch| character into the |buffer_| and updates the |count_| of
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // characters that are currently supposed to be in the buffer.
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns "false", iff the buffer was already full.
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // N.B. |count_| increases even if no characters have been written. This is
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // needed so that GetCount() can return the number of bytes that should
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // have been allocated for the |buffer_|.
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline bool Out(char ch) {
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (size_ >= 1 && count_ < size_) {
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      buffer_[count_] = ch;
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return IncrementCountByOne();
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // |count_| still needs to be updated, even if the buffer has been
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // filled completely. This allows SafeSPrintf() to return the number of
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // bytes that should have been emitted.
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    IncrementCountByOne();
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Inserts |padding|-|len| bytes worth of padding into the |buffer_|.
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |count_| will also be incremented by the number of bytes that were meant
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // to be emitted. The |pad| character is typically either a ' ' space
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // or a '0' zero, but other non-NUL values are legal.
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns "false", iff the the |buffer_| filled up (i.e. |count_|
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // overflowed |size_|) at any time during padding.
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline bool Pad(char pad, size_t padding, size_t len) {
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(pad);
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(padding >= 0 && padding <= kSSizeMax);
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(len >= 0);
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (; padding > len; --padding) {
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (!Out(pad)) {
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (--padding) {
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          IncrementCount(padding-len);
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        return false;
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // POSIX doesn't define any async-signal-safe function for converting
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // an integer to ASCII. Define our own version.
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This also gives us the ability to make the function a little more
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // powerful and have it deal with |padding|, with truncation, and with
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // predicting the length of the untruncated output.
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // IToASCII() converts an integer |i| to ASCII.
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Unlike similar functions in the standard C library, it never appends a
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // NUL character. This is left for the caller to do.
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // While the function signature takes a signed int64_t, the code decides at
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // run-time whether to treat the argument as signed (int64_t) or as unsigned
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // (uint64_t) based on the value of |sign|.
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // It supports |base|s 2 through 16. Only a |base| of 10 is allowed to have
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // a |sign|. Otherwise, |i| is treated as unsigned.
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // For bases larger than 10, |upcase| decides whether lower-case or upper-
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // case letters should be used to designate digits greater than 10.
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Padding can be done with either '0' zeros or ' ' spaces. Padding has to
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // be positive and will always be applied to the left of the output.
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Prepends a |prefix| to the number (e.g. "0x"). This prefix goes to
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the left of |padding|, if |pad| is '0'; and to the right of |padding|
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // if |pad| is ' '.
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns "false", if the |buffer_| overflowed at any time.
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool IToASCII(bool sign, bool upcase, int64_t i, int base,
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                char pad, size_t padding, const char* prefix);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Increments |count_| by |inc| unless this would cause |count_| to
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // overflow |kSSizeMax-1|. Returns "false", iff an overflow was detected;
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // it then clamps |count_| to |kSSizeMax-1|.
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline bool IncrementCount(size_t inc) {
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // "inc" is either 1 or a "padding" value. Padding is clamped at
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // run-time to at most kSSizeMax-1. So, we know that "inc" is always in
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // the range 1..kSSizeMax-1.
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // This allows us to compute "kSSizeMax - 1 - inc" without incurring any
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // integer overflows.
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(inc <= kSSizeMax - 1);
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (count_ > kSSizeMax - 1 - inc) {
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      count_ = kSSizeMax - 1;
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return false;
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      count_ += inc;
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return true;
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Convenience method for the common case of incrementing |count_| by one.
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline bool IncrementCountByOne() {
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return IncrementCount(1);
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Return the current insertion point into the buffer. This is typically
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // at |buffer_| + |count_|, but could be before that if truncation
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // happened. It always points to one byte past the last byte that was
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // successfully placed into the |buffer_|.
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  inline char* GetInsertionPoint() const {
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    size_t idx = count_;
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (idx > size_) {
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      idx = size_;
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return buffer_ + idx;
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // User-provided buffer that will receive the fully formatted output string.
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  char* buffer_;
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Number of bytes that are available in the buffer excluding the trailing
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // NUL byte that will be added by the destructor.
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const size_t size_;
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Number of bytes that would have been emitted to the buffer, if the buffer
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // was sufficiently big. This number always excludes the trailing NUL byte
27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // and it is guaranteed to never grow bigger than kSSizeMax-1.
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t count_;
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Buffer);
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base,
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      char pad, size_t padding, const char* prefix) {
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Sanity check for parameters. None of these should ever fail, but see
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // above for the rationale why we can't call CHECK().
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(base >= 2);
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(base <= 16);
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(!sign || base == 10);
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(pad == '0' || pad == ' ');
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(padding >= 0);
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(padding <= kSSizeMax);
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DEBUG_CHECK(!(sign && prefix && *prefix));
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Handle negative numbers, if the caller indicated that |i| should be
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // treated as a signed number; otherwise treat |i| as unsigned (even if the
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // MSB is set!)
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Details are tricky, because of limited data-types, but equivalent pseudo-
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // code would look like:
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   if (sign && i < 0)
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //     prefix = "-";
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //   num = abs(i);
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int minint = 0;
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  uint64_t num;
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (sign && i < 0) {
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    prefix = "-";
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Turn our number positive.
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (i == std::numeric_limits<int64_t>::min()) {
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // The most negative integer needs special treatment.
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      minint = 1;
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      num = static_cast<uint64_t>(-(i + 1));
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // "Normal" negative numbers are easy.
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      num = static_cast<uint64_t>(-i);
31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    num = static_cast<uint64_t>(i);
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // If padding with '0' zero, emit the prefix or '-' character now. Otherwise,
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // make the prefix accessible in reverse order, so that we can later output
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // it right between padding and the number.
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We cannot choose the easier approach of just reversing the number, as that
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // fails in situations where we need to truncate numbers that have padding
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // and/or prefixes.
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char* reverse_prefix = NULL;
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (prefix && *prefix) {
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (pad == '0') {
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      while (*prefix) {
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (padding) {
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          --padding;
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        Out(*prefix++);
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      prefix = NULL;
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      for (reverse_prefix = prefix; *reverse_prefix; ++reverse_prefix) {
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    prefix = NULL;
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const size_t prefix_length = reverse_prefix - prefix;
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Loop until we have converted the entire number. Output at least one
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // character (i.e. '0').
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t start = count_;
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t discarded = 0;
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool started = false;
34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  do {
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Make sure there is still enough space left in our output buffer.
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (count_ >= size_) {
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (start < size_) {
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // It is rare that we need to output a partial number. But if asked
35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // to do so, we will still make sure we output the correct number of
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // leading digits.
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Since we are generating the digits in reverse order, we actually
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // have to discard digits in the order that we have already emitted
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // them. This is essentially equivalent to:
35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        //   memmove(buffer_ + start, buffer_ + start + 1, size_ - start - 1)
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for (char* move = buffer_ + start, *end = buffer_ + size_ - 1;
35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             move < end;
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             ++move) {
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          *move = move[1];
36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        ++discarded;
36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        --count_;
36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      } else if (count_ - size_ > 1) {
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Need to increment either |count_| or |discarded| to make progress.
36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // The latter is more efficient, as it eventually triggers fast
36658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // handling of padding. But we have to ensure we don't accidentally
36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // change the overall state (i.e. switch the state-machine from
36858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // discarding to non-discarding). |count_| needs to always stay
36958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // bigger than |size_|.
37058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        --count_;
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        ++discarded;
37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
37558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Output the next digit and (if necessary) compensate for the most
37658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // negative integer needing special treatment. This works because,
37758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // no matter the bit width of the integer, the lowest-most decimal
37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // integer always ends in 2, 4, 6, or 8.
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!num && started) {
38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (reverse_prefix > prefix) {
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        Out(*--reverse_prefix);
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      } else {
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        Out(pad);
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      started = true;
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]);
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    minint = 0;
39158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    num /= base;
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Add padding, if requested.
39458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (padding > 0) {
39558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      --padding;
39658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
39758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Performance optimization for when we are asked to output excessive
39858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // padding, but our output buffer is limited in size.  Even if we output
39958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // a 64bit number in binary, we would never write more than 64 plus
40058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // prefix non-padding characters. So, once this limit has been passed,
40158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // any further state change can be computed arithmetically; we know that
40258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // by this time, our entire final output consists of padding characters
40358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // that have all already been output.
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (discarded > 8*sizeof(num) + prefix_length) {
40558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        IncrementCount(padding);
40658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        padding = 0;
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } while (num || padding || (reverse_prefix > prefix));
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Conversion to ASCII actually resulted in the digits being in reverse
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // order. We can't easily generate them in forward order, as we can't tell
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the number of characters needed until we are done converting.
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // So, now, we reverse the string (except for the possible '-' sign).
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  char* front = buffer_ + start;
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  char* back = GetInsertionPoint();
41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  while (--back > front) {
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    char ch = *back;
41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    *back = *front;
42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    *front++ = ch;
42158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
42258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  IncrementCount(discarded);
42458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return !discarded;
42558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
42658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // anonymous namespace
42858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace internal {
43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt, const Arg* args,
43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const size_t max_args) {
43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Make sure that at least one NUL byte can be written, and that the buffer
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // never overflows kSSizeMax. Not only does that use up most or all of the
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // address space, it also would result in a return code that cannot be
43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // represented.
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (static_cast<ssize_t>(sz) < 1) {
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return -1;
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else if (sz > kSSizeMax) {
44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sz = kSSizeMax;
44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Iterate over format string and interpret '%' arguments as they are
44458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // encountered.
44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Buffer buffer(buf, sz);
44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  size_t padding;
44758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  char pad;
44858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (unsigned int cur_arg = 0; *fmt && !buffer.OutOfAddressableSpace(); ) {
44958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (*fmt++ == '%') {
45058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      padding = 0;
45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      pad = ' ';
45258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      char ch = *fmt++;
45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    format_character_found:
45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      switch (ch) {
45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case '0': case '1': case '2': case '3': case '4':
45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case '5': case '6': case '7': case '8': case '9':
45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Found a width parameter. Convert to an integer value and store in
45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // "padding". If the leading digit is a zero, change the padding
45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // character from a space ' ' to a zero '0'.
46058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        pad = ch == '0' ? '0' : ' ';
46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for (;;) {
46258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // The maximum allowed padding fills all the available address
46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // space and leaves just enough space to insert the trailing NUL.
46458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          const size_t max_padding = kSSizeMax - 1;
46558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (padding > max_padding/10 ||
46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              10*padding > max_padding - (ch - '0')) {
46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            DEBUG_CHECK(padding <= max_padding/10 &&
46858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        10*padding <= max_padding - (ch - '0'));
46958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // Integer overflow detected. Skip the rest of the width until
47058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // we find the format character, then do the normal error handling.
47158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          padding_overflow:
47258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            padding = max_padding;
47358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            while ((ch = *fmt++) >= '0' && ch <= '9') {
47458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            }
47558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            if (cur_arg < max_args) {
47658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              ++cur_arg;
47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            }
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            goto fail_to_expand;
47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          padding = 10*padding + ch - '0';
48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (padding > max_padding) {
48258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // This doesn't happen for "sane" values of kSSizeMax. But once
48358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // kSSizeMax gets smaller than about 10, our earlier range checks
48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // are incomplete. Unittests do trigger this artificial corner
48558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // case.
48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            DEBUG_CHECK(padding <= max_padding);
48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            goto padding_overflow;
48858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
48958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          ch = *fmt++;
49058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (ch < '0' || ch > '9') {
49158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // Reached the end of the width parameter. This is where the format
49258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // character is found.
49358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            goto format_character_found;
49458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break;
49758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'c': {  // Output an ASCII character.
49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Check that there are arguments left to be inserted.
49958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (cur_arg >= max_args) {
50058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          DEBUG_CHECK(cur_arg < max_args);
50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto fail_to_expand;
50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
50358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
50458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Check that the argument has the expected type.
50558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const Arg& arg = args[cur_arg++];
50658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (arg.type != Arg::INT && arg.type != Arg::UINT) {
50758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT);
50858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto fail_to_expand;
50958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
51058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Apply padding, if needed.
51258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        buffer.Pad(' ', padding, 1);
51358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
51458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Convert the argument to an ASCII character and output it.
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        char ch = static_cast<char>(arg.integer.i);
51658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (!ch) {
51758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto end_of_output_buffer;
51858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
51958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        buffer.Out(ch);
52058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break; }
52158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'd':    // Output a possibly signed decimal value.
52258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'o':    // Output an unsigned octal value.
52358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'x':    // Output an unsigned hexadecimal value.
52458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'X':
52558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 'p': {  // Output a pointer value.
52658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Check that there are arguments left to be inserted.
52758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (cur_arg >= max_args) {
52858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          DEBUG_CHECK(cur_arg < max_args);
52958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto fail_to_expand;
53058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
53158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
53258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const Arg& arg = args[cur_arg++];
53358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        int64_t i;
53458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const char* prefix = NULL;
53558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (ch != 'p') {
53658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // Check that the argument has the expected type.
53758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (arg.type != Arg::INT && arg.type != Arg::UINT) {
53858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            DEBUG_CHECK(arg.type == Arg::INT || arg.type == Arg::UINT);
53958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            goto fail_to_expand;
54058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          i = arg.integer.i;
54258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (ch != 'd') {
54458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // The Arg() constructor automatically performed sign expansion on
54558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // signed parameters. This is great when outputting a %d decimal
54658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // number, but can result in unexpected leading 0xFF bytes when
54758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // outputting a %x hexadecimal number. Mask bits, if necessary.
54858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // We have to do this here, instead of in the Arg() constructor, as
54958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // the Arg() constructor cannot tell whether we will output a %d
55058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            // or a %x. Only the latter should experience masking.
551116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            if (arg.integer.width < sizeof(int64_t)) {
552116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              i &= (1LL << (8*arg.integer.width)) - 1;
55358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            }
55458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
55558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        } else {
55658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // Pointer values require an actual pointer or a string.
55758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          if (arg.type == Arg::POINTER) {
55858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            i = reinterpret_cast<uintptr_t>(arg.ptr);
55958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          } else if (arg.type == Arg::STRING) {
56058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            i = reinterpret_cast<uintptr_t>(arg.str);
561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          } else if (arg.type == Arg::INT &&
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     arg.integer.width == sizeof(NULL) &&
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     arg.integer.i == 0) {  // Allow C++'s version of NULL
56458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            i = 0;
56558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          } else {
56658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            DEBUG_CHECK(arg.type == Arg::POINTER || arg.type == Arg::STRING);
56758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            goto fail_to_expand;
56858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
56958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
57058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          // Pointers always include the "0x" prefix.
57158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          prefix = "0x";
57258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
57358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
57458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Use IToASCII() to convert to ASCII representation. For decimal
57558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // numbers, optionally print a sign. For hexadecimal numbers,
57658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // distinguish between upper and lower case. %p addresses are always
57758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // printed as upcase. Supports base 8, 10, and 16. Prints padding
57858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // and/or prefixes, if so requested.
57958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        buffer.IToASCII(ch == 'd' && arg.type == Arg::INT,
58058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        ch != 'x', i,
58158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        ch == 'o' ? 8 : ch == 'd' ? 10 : 16,
58258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        pad, padding, prefix);
58358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break; }
58458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case 's': {
58558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Check that there are arguments left to be inserted.
58658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (cur_arg >= max_args) {
58758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          DEBUG_CHECK(cur_arg < max_args);
58858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto fail_to_expand;
58958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
59058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
59158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Check that the argument has the expected type.
59258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const Arg& arg = args[cur_arg++];
59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const char *s;
59458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (arg.type == Arg::STRING) {
59558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          s = arg.str ? arg.str : "<NULL>";
596116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        } else if (arg.type == Arg::INT && arg.integer.width == sizeof(NULL) &&
597116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   arg.integer.i == 0) {  // Allow C++'s version of NULL
59858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          s = "<NULL>";
59958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        } else {
60058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          DEBUG_CHECK(arg.type == Arg::STRING);
60158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto fail_to_expand;
60258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
60358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
60458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Apply padding, if needed. This requires us to first check the
60558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // length of the string that we are outputting.
60658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (padding) {
60758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          size_t len = 0;
60858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          for (const char* src = s; *src++; ) {
60958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            ++len;
61058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          }
61158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          buffer.Pad(' ', padding, len);
61258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
61358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Printing a string involves nothing more than copying it into the
61558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // output buffer and making sure we don't output more bytes than
61658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // available space; Out() takes care of doing that.
61758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        for (const char* src = s; *src; ) {
61858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          buffer.Out(*src++);
61958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
62058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break; }
62158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      case '%':
62258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Quoted percent '%' character.
62358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        goto copy_verbatim;
62458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      fail_to_expand:
62558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // C++ gives us tools to do type checking -- something that snprintf()
62658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // could never really do. So, whenever we see arguments that don't
62758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // match up with the format string, we refuse to output them. But
62858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // since we have to be extremely conservative about being async-
62958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // signal-safe, we are limited in the type of error handling that we
63058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // can do in production builds (in debug builds we can use
63158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // DEBUG_CHECK() and hope for the best). So, all we do is pass the
63258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // format string unchanged. That should eventually get the user's
63358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // attention; and in the meantime, it hopefully doesn't lose too much
63458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // data.
63558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      default:
63658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // Unknown or unsupported format character. Just copy verbatim to
63758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // output.
63858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        buffer.Out('%');
63958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        DEBUG_CHECK(ch);
64058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        if (!ch) {
64158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          goto end_of_format_string;
64258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        }
64358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        buffer.Out(ch);
64458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        break;
64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
64658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  copy_verbatim:
64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    buffer.Out(fmt[-1]);
64958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
65058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
65158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) end_of_format_string:
65258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) end_of_output_buffer:
65358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return buffer.GetCount();
65458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
65658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace internal
65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
65858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt) {
65958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Make sure that at least one NUL byte can be written, and that the buffer
66058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // never overflows kSSizeMax. Not only does that use up most or all of the
66158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // address space, it also would result in a return code that cannot be
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // represented.
66358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (static_cast<ssize_t>(sz) < 1) {
66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return -1;
66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else if (sz > kSSizeMax) {
66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sz = kSSizeMax;
66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Buffer buffer(buf, sz);
67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // In the slow-path, we deal with errors by copying the contents of
67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // "fmt" unexpanded. This means, if there are no arguments passed, the
67358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // SafeSPrintf() function always degenerates to a version of strncpy() that
67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // de-duplicates '%' characters.
67558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const char* src = fmt;
67658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (; *src; ++src) {
67758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    buffer.Out(*src);
67858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DEBUG_CHECK(src[0] != '%' || src[1] == '%');
67958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (src[0] == '%' && src[1] == '%') {
68058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ++src;
68158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
68258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
68358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return buffer.GetCount();
68458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
68558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
68658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace strings
68758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace base
688