Stephen Sprunk said:
This example shows how far you have diverged from sprintf(). From such
a claim, I would have expected something more like this:
nbitsinbuffer = smemf(buffer,
"%1lu" /* Image Descriptor, 8-bit little-endian unsigned int */
"%2lu" /* X-Pos, 16-bit little-endian unsigned int */
"%2lu" /* Top, 16-bit little-endian unsigned int */
"%2lu" /* Width, 16-bit little-endian unsigned int */
"%2lu" /* Height, 16-bit little-endian unsigned int */
/* following is the "Packed" Byte consisting of five bit fields */
"%3b" /* #colorbits, 3-bit field */
"%2b" /* reserved, 2-bit field */
"%1b" /* local colortable sort flag, 1-bit field */
"%1b" /* interlace flag, 1-bit field */
"%1b", /* local colortable flag, 1-bit field */
0x2C, col0, row0, ncols, nrows, ncolorbits, 0, 0, 0,
(colortable==NULL?0:1) );
Thanks for the alternative spec. I'll keep it in mind.
I agree that your format's more sprintf-like. Maybe I
should "deprecate" that literal requirement. More
about why in response to your specific remarks below...
Notice that whitespace is _not_ ignored and that there are ten arguments
corresponding to ten format specifiers.
Both of which I'd consider bad news. Certainly, ignoring
whitespace is different. But notice that your format string
has none. And likely never would, because how often is
whitespace going to be part of a binary packet format
specification? So it's basically no use for this particular
purpose.
And you also don't get constants in your formats.
Instead, you've got that 0x2C and 0,0,0 in the arguments
which "force-feeds" the "%1b" specifiers. And which
the user has to know about. Instead, I'm moving those
same 0x2C and 0's into the format string
preceding the %1b. Different, again, but serves
the purpose better. The user shouldn't have to
remember magic numbers like 0x2C, and where to put
them.
Instead, maybe some .h file with all the format
strings describing the packets for some particular
protocol/whatever would embed all that info and
hide it from the user. He'd just say something like,
#include "packetformatstrings.h"
unsigned char *thispacketbuffer = malloc(whatever);
...
smemf(thispacketbuffer, thispacketformatstring,
all,the,numbers,I,actually,care,about,and,no,others);
And that would do the entire job, with the user taking
care of his business only, and the binary packet formatting
pretty much entirely handled for him.
I also used %u rather than %d
since I'm pretty sure those ints are supposed to be unsigned (but I'm
not sure that makes a difference here).
Of course, your use of "%ld" to mean "little-endian word" rather than
"long signed integer" is a major difference as well, though that's
forgivable since you obviously need more control over representation
than sprintf()'s specifiers offer. When thinking it through, though,
that was the point at which I decided that trying to reuse those
specifiers was probably more trouble than it was worth.
Forget the characters %u vs %d and length modifier, flags, etc.
That's easily/trivially changed. In fact, I'd already changed
my mind to %<d or (%<u if you prefer) for little endian,
and the obvious for big, but might change it again.
Just focus on the functionality. The format string syntax,
at least so far as specifiers, flags, modifiers, etc are
concerned, can be decided later. For now, they're just
illustrative -- you have to write something while discussing it.