Without additional information on what your code does, I would recommend developing all of your interfaces as follows:
size_t foobar(char *dest, size_t buf_size, )
with semantics like snprintf :
dest points to a buffer of at least buf_size .- If
buf_size is zero, null / invalid pointers are valid for dest and nothing will be written. - If
buf_size nonzero, dest always null terminated. - Each
foobar function returns the length of the full, un truncated output; the output was truncated if buf_size less than or equal to the return value.
Thus, when the caller can easily find out the required size of the destination buffer, a sufficiently large buffer can be obtained in advance. If the caller cannot easily find out, he can call the function once with a null argument for buf_size or with a buffer that is "probably large enough" and only retry if you run out of free space.
You can also make a wrapped version of such calls, similar to the GNU asprintf function, but if you want your code to be as flexible as possible, I would avoid making any distribution in actual string functions. Handling the probability of a failure is always simpler at the caller level, and many subscribers can guarantee that a failure will never be possible using a local buffer or a buffer that was received much earlier in the program so that the success or failure of a larger operation is atomic (which greatly simplifies processing errors).
R .. Jan 2 '10 at 21:01 2011-01-02 21:01
source share