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" 13f678e45dSDimitry Andric #include "llvm/ADT/SmallVector.h" // for SmallVectorImpl 14f678e45dSDimitry Andric #include "llvm/ADT/StringRef.h" // for StringRef 15f678e45dSDimitry Andric 16f678e45dSDimitry Andric #include <assert.h> // for assert 17f678e45dSDimitry Andric #include <stdarg.h> // for va_end, va_list, va_copy 18f678e45dSDimitry Andric #include <stdio.h> // for vsnprintf, size_t 19f678e45dSDimitry Andric 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()) { 39f678e45dSDimitry Andric // The error formatted string didn't fit into our buffer, resize it 40f678e45dSDimitry Andric // to the 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