Re: [Libclc-developers] Re: contribution(?): string function ultostr()
Status: Planning
Brought to you by:
augestad
|
From: Hallvard B F. <h.b...@us...> - 2003-03-18 18:48:10
|
Michael B.Allen writes:
>Jan Engelhardt <je...@li...> wrote:
>
>>> *startp = ptr + size - 2;
>
> What would happen if size were 2, 1, or even 0? Those are legitimate
> values.
2 is OK with that code. 0 and 1 don't need to be, we can document
that size must be at least 2 and add clc_assert_arg(ultostr, size>1).
>>> clc_assert_arg(ultostr, base >= 2 && base <= 36);
>>> (...)
>>> if(base < 2 || base > 36) {
>>> errno = ERANGE;
>>> return NULL;
>>> }
I hope this doesn't spawn a too big error handling thread again, but I
think if the function fails with ERANGE when base is out of range, that
should be documented, well-defined behaviour - so there should not be an
assert which makes such an argument crash the program.
> What about negative values?
Not in an _unsigned_ long.
Some other points:
I think the output argument should be first, followed by the size
argument, similar to fread (and strcpy for the output argument).
You forgot to \0-terminate the output.
I'd prefer to get as few digits as possible returned instead of
'0'-padding the output. Even though this means doing memmove()
at the end. (Or we could return a pointer into the middle of the
string, but that invites bugs in the user's program.)
It shuold fail if the output buffer is too small.
... fail with ERANGE? Or is this our chance to invent our first CLC_E*
code - CLC_ENOSPC "not enough space"?
#include <string.h>
#include <errno.h>
#include "clc_assert.h"
char *
clc_ultostr(char *ptr, size_t size, unsigned long num, int base)
{
char *end, *end2;
const char *sym = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
clc_assert_not_null(clc_ultostr, ptr);
clc_assert_arg(clc_ultostr, size > 1);
if(base < 2 || base > 36) { /* or assert 2 <= base && base <= 36 */
errno = ERANGE;
return NULL;
}
end = end2 = ptr + size;
*--end = '\0';
do {
if (end == ptr) {
errno = ERANGE;
return NULL;
}
*--end = sym[num % base];
num /= base;
} while (num);
if (end != ptr)
memmove(ptr, end, end2 - end);
return ptr;
}
|