1f678e45dSDimitry Andric //===-- VASPrintf.cpp -------------------------------------------*- C++ -*-===//
2f678e45dSDimitry Andric //
3f678e45dSDimitry Andric //                     The LLVM Compiler Infrastructure
4f678e45dSDimitry Andric //
5f678e45dSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f678e45dSDimitry Andric // License. See LICENSE.TXT for details.
7f678e45dSDimitry Andric //
8f678e45dSDimitry Andric //===----------------------------------------------------------------------===//
9f678e45dSDimitry Andric 
10f678e45dSDimitry Andric #include "lldb/Utility/VASPrintf.h"
11f678e45dSDimitry Andric 
12f678e45dSDimitry Andric #include "llvm/ADT/SmallString.h"
13*b5893f02SDimitry Andric #include "llvm/ADT/SmallVector.h"
14*b5893f02SDimitry Andric #include "llvm/ADT/StringRef.h"
15f678e45dSDimitry Andric 
16*b5893f02SDimitry Andric #include <assert.h>
17*b5893f02SDimitry Andric #include <stdarg.h>
18*b5893f02SDimitry Andric #include <stdio.h>
19f678e45dSDimitry Andric 
VASprintf(llvm::SmallVectorImpl<char> & buf,const char * fmt,va_list args)20f678e45dSDimitry Andric bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
21f678e45dSDimitry Andric                              va_list args) {
22f678e45dSDimitry Andric   llvm::SmallString<16> error("<Encoding error>");
23f678e45dSDimitry Andric   bool result = true;
24f678e45dSDimitry Andric 
25f678e45dSDimitry Andric   // Copy in case our first call to vsnprintf doesn't fit into our buffer
26f678e45dSDimitry Andric   va_list copy_args;
27f678e45dSDimitry Andric   va_copy(copy_args, args);
28f678e45dSDimitry Andric 
29f678e45dSDimitry Andric   buf.resize(buf.capacity());
30f678e45dSDimitry Andric   // Write up to `capacity` bytes, ignoring the current size.
31f678e45dSDimitry Andric   int length = ::vsnprintf(buf.data(), buf.size(), fmt, args);
32f678e45dSDimitry Andric   if (length < 0) {
33f678e45dSDimitry Andric     buf = error;
34f678e45dSDimitry Andric     result = false;
35f678e45dSDimitry Andric     goto finish;
36f678e45dSDimitry Andric   }
37f678e45dSDimitry Andric 
38f678e45dSDimitry Andric   if (size_t(length) >= buf.size()) {
394ba319b5SDimitry Andric     // The error formatted string didn't fit into our buffer, resize it to the
404ba319b5SDimitry Andric     // exact needed size, and retry
41f678e45dSDimitry Andric     buf.resize(length + 1);
42f678e45dSDimitry Andric     length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
43f678e45dSDimitry Andric     if (length < 0) {
44f678e45dSDimitry Andric       buf = error;
45f678e45dSDimitry Andric       result = false;
46f678e45dSDimitry Andric       goto finish;
47f678e45dSDimitry Andric     }
48f678e45dSDimitry Andric     assert(size_t(length) < buf.size());
49f678e45dSDimitry Andric   }
50f678e45dSDimitry Andric   buf.resize(length);
51f678e45dSDimitry Andric 
52f678e45dSDimitry Andric finish:
53f678e45dSDimitry Andric   va_end(args);
54f678e45dSDimitry Andric   va_end(copy_args);
55f678e45dSDimitry Andric   return result;
56f678e45dSDimitry Andric }
57