VASprintf.cpp revision 317027
1168404Spjd//===-- VASPrintf.cpp -------------------------------------------*- C++ -*-===//
2168404Spjd//
3168404Spjd//                     The LLVM Compiler Infrastructure
4168404Spjd//
5168404Spjd// This file is distributed under the University of Illinois Open Source
6168404Spjd// License. See LICENSE.TXT for details.
7168404Spjd//
8168404Spjd//===----------------------------------------------------------------------===//
9168404Spjd
10168404Spjd#include "lldb/Utility/VASPrintf.h"
11168404Spjd
12168404Spjd#include "llvm/ADT/SmallString.h"
13168404Spjd#include "llvm/ADT/SmallVector.h" // for SmallVectorImpl
14168404Spjd#include "llvm/ADT/StringRef.h"   // for StringRef
15168404Spjd
16168404Spjd#include <assert.h> // for assert
17168404Spjd#include <stdarg.h> // for va_end, va_list, va_copy
18168404Spjd#include <stdio.h>  // for vsnprintf, size_t
19168404Spjd
20168404Spjdbool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
21168404Spjd                             va_list args) {
22168404Spjd  llvm::SmallString<16> error("<Encoding error>");
23219089Spjd  bool result = true;
24249195Smm
25268658Sdelphij  // Copy in case our first call to vsnprintf doesn't fit into our buffer
26247265Smm  va_list copy_args;
27168404Spjd  va_copy(copy_args, args);
28168404Spjd
29168404Spjd  buf.resize(buf.capacity());
30251629Sdelphij  // Write up to `capacity` bytes, ignoring the current size.
31251629Sdelphij  int length = ::vsnprintf(buf.data(), buf.size(), fmt, args);
32168404Spjd  if (length < 0) {
33168404Spjd    buf = error;
34168404Spjd    result = false;
35168404Spjd    goto finish;
36168404Spjd  }
37168404Spjd
38168404Spjd  if (size_t(length) >= buf.size()) {
39168404Spjd    // The error formatted string didn't fit into our buffer, resize it
40168404Spjd    // to the exact needed size, and retry
41168404Spjd    buf.resize(length + 1);
42168404Spjd    length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
43168404Spjd    if (length < 0) {
44168404Spjd      buf = error;
45168404Spjd      result = false;
46219089Spjd      goto finish;
47168404Spjd    }
48168404Spjd    assert(size_t(length) < buf.size());
49219089Spjd  }
50168404Spjd  buf.resize(length);
51168404Spjd
52168404Spjdfinish:
53168404Spjd  va_end(args);
54168404Spjd  va_end(copy_args);
55168404Spjd  return result;
56168404Spjd}
57168404Spjd