1 | //===-- VASprintf.cpp -----------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Utility/VASPrintf.h" |
10 | |
11 | #include "llvm/ADT/SmallString.h" |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "llvm/ADT/StringRef.h" |
14 | |
15 | #include <cassert> |
16 | #include <cstdarg> |
17 | #include <cstdio> |
18 | |
19 | bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt, |
20 | va_list args) { |
21 | llvm::SmallString<16> error("<Encoding error>" ); |
22 | bool result = true; |
23 | |
24 | // Copy in case our first call to vsnprintf doesn't fit into our buffer |
25 | va_list copy_args; |
26 | va_copy(copy_args, args); |
27 | |
28 | buf.resize(N: buf.capacity()); |
29 | // Write up to `capacity` bytes, ignoring the current size. |
30 | int length = ::vsnprintf(s: buf.data(), maxlen: buf.size(), format: fmt, arg: args); |
31 | if (length < 0) { |
32 | buf = error; |
33 | result = false; |
34 | goto finish; |
35 | } |
36 | |
37 | if (size_t(length) >= buf.size()) { |
38 | // The error formatted string didn't fit into our buffer, resize it to the |
39 | // exact needed size, and retry |
40 | buf.resize(N: length + 1); |
41 | length = ::vsnprintf(s: buf.data(), maxlen: buf.size(), format: fmt, arg: copy_args); |
42 | if (length < 0) { |
43 | buf = error; |
44 | result = false; |
45 | goto finish; |
46 | } |
47 | assert(size_t(length) < buf.size()); |
48 | } |
49 | buf.resize(N: length); |
50 | |
51 | finish: |
52 | va_end(args); |
53 | va_end(copy_args); |
54 | return result; |
55 | } |
56 | |