Alex Suykov b1d4b246c6 rework makefiles / thin lib.a %!s(int64=4) %!d(string=hai) anos
..
Makefile b1d4b246c6 rework makefiles / thin lib.a %!s(int64=4) %!d(string=hai) anos
README e000a5914c lib: docs update on fmt* and parse* %!s(int64=7) %!d(string=hai) anos
fmtbyte.c 2425b4a1e5 lib: uniform (p,e) arguments for some fmt* calls %!s(int64=7) %!d(string=hai) anos
fmtbytes.c 0b80d36f60 get rid of arch/*/bits/ints.h %!s(int64=7) %!d(string=hai) anos
fmtchar.c 61ac1617fb lib: revert fmtchar to a regular function %!s(int64=4) %!d(string=hai) anos
fmterr.c 9fd8e80a9b lib: avoid unrestricted strings %!s(int64=4) %!d(string=hai) anos
fmthex.c 5cfbf5d84f lib: trailing whitespace cleanup %!s(int64=6) %!d(string=hai) anos
fmtint32.c 5cfbf5d84f lib: trailing whitespace cleanup %!s(int64=6) %!d(string=hai) anos
fmtint64.c 5cfbf5d84f lib: trailing whitespace cleanup %!s(int64=6) %!d(string=hai) anos
fmtip.c 341fb72ff1 lib: fmtip() %!s(int64=8) %!d(string=hai) anos
fmtmac.c 9fd8e80a9b lib: avoid unrestricted strings %!s(int64=4) %!d(string=hai) anos
fmtpad.c 6198362875 lib: fmtpadr, and sanity checks in fmtpad %!s(int64=8) %!d(string=hai) anos
fmtpad0.c f8063e287c lib: pad0 %!s(int64=8) %!d(string=hai) anos
fmtpadr.c 6198362875 lib: fmtpadr, and sanity checks in fmtpad %!s(int64=8) %!d(string=hai) anos
fmtraw.c d9b9c3d78e lib: fix warn() fmt/str/end usage %!s(int64=4) %!d(string=hai) anos
fmtsize.c a21dc22f95 lib: fmtsize should round sizes to nearest %!s(int64=7) %!d(string=hai) anos
fmtstr.c 9fd8e80a9b lib: avoid unrestricted strings %!s(int64=4) %!d(string=hai) anos
fmtstre.c 9fd8e80a9b lib: avoid unrestricted strings %!s(int64=4) %!d(string=hai) anos
fmtstrn.c 9fd8e80a9b lib: avoid unrestricted strings %!s(int64=4) %!d(string=hai) anos
fmttm.c 2425b4a1e5 lib: uniform (p,e) arguments for some fmt* calls %!s(int64=7) %!d(string=hai) anos
fmtulp.c 5cfbf5d84f lib: trailing whitespace cleanup %!s(int64=6) %!d(string=hai) anos
fmtx32.c 14af7c3586 lib: fix temp var types in fmtx32/fmtx64 %!s(int64=7) %!d(string=hai) anos
fmtx64.c 05faed18f9 lib: stfu gcc that alias is fine %!s(int64=6) %!d(string=hai) anos
parsebyte.c c0b728f26c lib: signed/unsigned update %!s(int64=7) %!d(string=hai) anos
parsebytes.c 0b80d36f60 get rid of arch/*/bits/ints.h %!s(int64=7) %!d(string=hai) anos
parsehex.c cb0e84bbf6 lib: parse[int]("") should fail %!s(int64=7) %!d(string=hai) anos
parseint.c cb0e84bbf6 lib: parse[int]("") should fail %!s(int64=7) %!d(string=hai) anos
parseint64.c 0b80d36f60 get rid of arch/*/bits/ints.h %!s(int64=7) %!d(string=hai) anos
parseip.c c0b728f26c lib: signed/unsigned update %!s(int64=7) %!d(string=hai) anos
parseipmask.c c0b728f26c lib: signed/unsigned update %!s(int64=7) %!d(string=hai) anos
parselong.c cb0e84bbf6 lib: parse[int]("") should fail %!s(int64=7) %!d(string=hai) anos
parsemac.c c0b728f26c lib: signed/unsigned update %!s(int64=7) %!d(string=hai) anos
parseoct.c cb0e84bbf6 lib: parse[int]("") should fail %!s(int64=7) %!d(string=hai) anos
parseuint.c dd08351ea4 lib: parseuint %!s(int64=7) %!d(string=hai) anos
parseulong.c cb0e84bbf6 lib: parse[int]("") should fail %!s(int64=7) %!d(string=hai) anos
parsexlong.c 67c96a6d08 lib: parsexlong %!s(int64=7) %!d(string=hai) anos

README

String formatting routines
~~~~~~~~~~~~~~~~~~~~~~~~~~
fmt* functions implement printf-style formatting fields:

%c fmtchar
%s fmtstr
%li fmtlong
%lu fmtulong
%i fmti32
%lli fmti64
%*lu fmtulp

All functions of this kind take start and end of the buffer to print to,
and return a pointer past the last character written.
Typical setup for these functions looks like this:

char buf[100]; /* the buffer to print to */
char* p = buf;
char* e = buf + sizeof(buf) - 1; /* leaving space for \0 */

p = fmt...(p, e, ...);
p = fmt...(p, e, ...);
p = fmt...(p, e, ...);
...
p = fmt...(p, e, ...);

*p = '\0'; /* optional */

By the end of the code, (p - buf) is the length of the resulting string.


Why not printf
~~~~~~~~~~~~~~
The reason for this over common printf() is that printf does runtime parsing
of its format string. Any reasonable printf implementation would need to link
*all* supported formatters even if the application in question only needs one
or two. With fmt*, only the functions used get linked into the executable.

In addition, fmt style code is easier to compose, and custom writing custom
formatters is trivial. Unlike with printf.

Another way to view fmt is that it's printf with pre-compile-time format
parsing. C cannot do compile-time parsing for something like printf, so
it needs to be done manually.


String parsing
~~~~~~~~~~~~~~
The opposite (scanf-like) routines are somewhat different:

p = parseint(p, &value);

They take a pointer to the start of the string, and return pointer past
the last character parsed, or NULL if parsing failed.
Unlike fmt*, these alway work on 0-terminated strings.

The reason they are not fully symmetrical is that in vast majority of cases
the strings being parsed are 0-terminated command line arguments. Using (p,e)
convention with those would result in clumsy code. Having both (p,e) and some
sort of fallback (p)-only functions has been considered, but it would make
the most common use cases unnecessary complicated, and there's no point yet
in keeping two parallel version of parsing routines.

Common invocation for parse* functions is

if((p = parse...(p, &value)) && !*p)

The second condition makes sure the whole string has been parsed and there's
no trailing garbage.