Skip to content

Instantly share code, notes, and snippets.

@emilk
Created March 15, 2015 14:18
Show Gist options
  • Save emilk/dfc1071014f7b81917ff to your computer and use it in GitHub Desktop.
Save emilk/dfc1071014f7b81917ff to your computer and use it in GitHub Desktop.
strprintf
std::string strprintf(const char * __restrict, va_list) __printflike(1, 0);
std::string strprintf(const char * __restrict, ...) __printflike(1, 2);
std::string strprintf(const char* format, va_list vlist)
{
#if 1
char* buff = nullptr;
int ret = vasprintf(&buff, format, vlist);
ASSERT(ret >= 0);
std::string str = buff;
free(buff);
return str;
#else
int bytes_needed = vsnprintf(nullptr, 0, format, vlist);
ASSERT(bytes_needed >= 0);
//std::string str; // str.data() is const char* (grrr)
std::vector<char> str;
str.resize(bytes_needed + 1);
vsnprintf(str.data(), str.size(), format, vlist);
return std::string(std::begin(str), std::end(str)); // TODO: avoid this copy
#endif
}
std::string strprintf(const char* format, ...)
{
va_list vlist;
va_start(vlist, format);
auto str = strprintf(format, vlist);
va_end(vlist);
return str;
}
@yoedstavi
Copy link

can I propose the following implementation instead?

std::string strprintf(const char *fromat, ...)
{
	std::string s;
	s.resize(128); // best guess
	char *buff = const_cast<char *>(s.data());

	va_list arglist;
	va_start(arglist, fromat);
	auto len = vsnprintf(buff, 128, fromat, arglist);
	va_end(arglist);

	if (len > 127)
	{
		va_start(arglist, fromat);
		s.resize(len + 1); // leave room for null terminator
		buff = const_cast<char *>(s.data());
		len = vsnprintf(buff, len+1, fromat, arglist);
		va_end(arglist);
	}
	s.resize(len);
	return s; // move semantics FTW
}

@etorth
Copy link

etorth commented Feb 21, 2018

std::string strprintf(const char* format, va_list vlist)

problem is for va_list we don't even know if it has a copy constructor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment