Adding formatting support to a custom string implementation - C
I have a C
application (not using C99 features) that does some heavy string processing. Since the string lengths are not known, statically allocated buffers is not an option for me. I have created a simple string
implementation which will abstract the null termination and dynamic expansion of buffers.
Here is how it looks like,
struct strbuf {
char *buffer; /* null terminated buffer */
size_t length; /* length of the string excluding null terminator */
size_t allocated; /* total memory allocated */
};
add
function which adds the supplied string into the buffer.
int strbuf_add(struct strbuf *string, const char *c)
{
if(string == NULL) return 0;
while(*c != '\0') {
if(!add_char(string, *c++))
return 0;
}
return 1;
}
static int add_char(struct strbuf *string, char c)
{
size_t space_available;
assert(string != NULL);
space_available = string->allocated - string->length;
if(space_available <= 1) {
if(!grow_buffer(string)) {
return 0;
}
}
string->buffer[string->length++] = c;
string->buffer[string->length] = '\0';
return 1;
}
Now, I need to add a new method something like, addformatted
which will take a format like sprintf
. I am wondering what would be the best way to do this? Following are my thoughts.
- Use
vsnprintf
. But I am not sure that this is portable a开发者_运维知识库nd has got the same behaviour on all platforms. - Write a format parser myself. But this seems to be more work.
Any help in implementing this would be great. I am only interested in portable solutions.
- Dev Env : Linux with GCC
- Expected to compile on MSVC
snprintf
is the way to go and has well-defined behavior, but there are some broken implementations where it returns the wrong values when the buffer is too small. Personally I would just ignore broken implementations unless you really need to use one, or provide a custom implementation of the whole printf
family to replace the system version on such broken systems. Otherwise you need to research the broken behavior these systems exhibit and find out how to write workarounds. It might require progressively enlarging the buffer over and over until your call succeeds.
When you use sprintf, you must have some idea of what the resulting string length will be, or else you use snprintf and shield yourself from buffer overflows.
If you want this kind of interface, you can create a function that wraps snprintf and takes as argument a buffer length, and expand your string the required amount before calling snprintf.
精彩评论