I use the standard vsnprintf() function for text formatting. It works well, but I must delete the buffer out of the function scope. I don't want to do it. I want to auto manage it. And I want to return const char*.
First, I thought that I can simply use a static buffer. But then I have a problem that I can't save multiple format() results and join them at the end, because the buffer is overwritten.
So, I wrote the function with a const char* pool. It has a limit of 1024 buffers, which is enough for my purposes, but I feel that this is not a good way to go.
Any idea how to deal with this issue?
Here is the original function:
const char * format(const char* fmt, ...)
{
va_list vl;
va_start(vl, fmt);
int size = vsnprintf(0, 0, fmt, vl) + sizeof('\0');
va_end(vl);
char *buffer = new char [size];
va_start(vl, fmt);
size = vsnprintf(buffer, size, fmt, vl);
va_end(vl);
return buffer;
}
In some situations, I do several format() operations, so I need to save the result and merge it at the end. So, I rewrote the function to use the pool:
const char * format3(const char* fmt, ...) {
static char **pool = new char *[1024]();
static int sizes[1024];
static int index = 0;
static bool firstLoop = true;
va_list vl;
va_start(vl, fmt);
int size = vsnprintf(0, 0, fmt, vl) + sizeof('\0');
va_end(vl);
char *buffer;
if (firstLoop) {
buffer = new char [size];
pool[index] = buffer;
} else {
buffer = pool[index];
int s = sizes[index];
if (s < size) {
delete [] buffer;
buffer = new char [size];
pool[index] = buffer;
}
}
va_start(vl, fmt);
size = vsnprintf(buffer, size, fmt, vl);
va_end(vl);
index++;
if (index == 1024) {
index = 0;
firstLoop = false;
}
return buffer;
}
In C, you do not deal with the issue. In C, I would expect users to want to deallocate memory themselves, it is completely normal. In C, do not hide deallocation, let the users now what they are doing.
In C++, there are the whole object lifetime and object destructors are executed at the end of variable scope. In C++, use
std::string, which exists to manage string memory and will deallocate strings automatically.Overall, in C++, there are sstreams, in particular
std::stringstreamand in newer C++ there isstd::format. You would typically prefer them in C++.sizeof('\0')sounds confusing, it is 4 in C and 1 in C++. Just+ 1. When you are dealing with C strings, it is typical that your code is sprinkled with+ 1everywhere.