home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!cs.utexas.edu!sun-barr!male.EBay.Sun.COM!exodus.Eng.Sun.COM!appserv.Eng.Sun.COM!sun!amdcad!BitBlocks.com!bvs
- From: bvs@BitBlocks.COM (Bakul Shah)
- Newsgroups: comp.lang.c
- Subject: Re: (Help) dynamic use of sprintf ?
- Message-ID: <1992Jul21.201712.20985@BitBlocks.COM>
- Date: 21 Jul 92 20:17:12 GMT
- References: <brself.711345285@hal>
- Organization: Bit Blocks, Inc.
- Lines: 95
-
- brself@hal.gnu.ai.mit.edu (Ben Self) writes:
- >
- > Could anyone please help me with a C programming dilemma that has plagued me
- > for ages.
- >
- > Often when formatting strings or converting numerics to alphas, sprintf ()
- > appears as an extremely attractive possibility. Unfortunately, it does not
- > fit well with dynamic allocation nor is it easily safe guarded from
- > segmentation faults and bus errors.
- ...
- > We must sell -- any serious offer will be accepted :-)
- >
- > Thanks in advance.
-
- Here is another solution that will work for this and many other
- formatting uses. PD source code on request.
-
- I have a vfprintf like function, called `vfnprintf' that takes a
- _function pointer_ instead of a FILE *. vfnprintf calls this
- function, possibly multiple times, to drain already formatted
- characters. _You_ supply the function. Here is an example use.
-
- #include <stdarg.h>
-
- struct snstate {
- int size;
- int offset;
- char * buffer;
- };
-
- /* typedef for a function ptr */
- typedef int (*_vfn_t)(void * st, const char * string, unsigned int count);
-
- int vfnprintf(_vfn_t fn, void * st, const char * format, va_list args);
-
- /*
- * a function to drain the formatted chars
- * It doesn't allow a write beyond the
- * end of st->bufer and nul terminates
- * the copied string.
- */
- int sndrain(struct snstate * st, char * str, int count) {
- int space = st->size - st->offset - 1;
- if (count > space)
- count = space;
- if (count > 0) {
- memcpy(st->buffer + st->offset, str, count);
- st->offset += count;
- st->buffer[st->offset] = '\0';
- }
- return count;
- }
-
- /*
- * given sndrain and vfnprintf, snprintf can be defined to
- * to `sprintf' to a string of given size
- */
- int snprintf(char * str, int size, const char * fmt, ...) {
- int count;
- va_list args;
- struct snstate snstate;
- snstate.size = size;
- snstate.offset = 0;
- snstate.buffer = str;
-
- va_start(args, fmt);
- count = vfnprintf((_vfn_t)sndrain, &snstate, fmt, args);
- va_end(args);
- return count;
- }
-
- You can equally easily provide another function that allocates
- more space as needed. Since the function ptr arg to vfnprintf
- takes a ptr to a `state' struct, you can even collect the output
- from multiple snprintf calls. (And if snstate->buffer mmap()ed
- to some file then who needs stdio! But I digress.) vfnprintf is
- low level enough that stdio can be built atop it though you
- probably wouldn't want to do so for performance reasons.
-
- vfnprintf will call `fn' whenever it wants to output one or more
- formatted chars. Function `fn' should return the number of chars
- it could drain, 0 if none and -1 to indicate an error. It can
- keep any needed state in `st' (unfortunately, C doesn't have
- nested functions or else the vfnprintf interface would've been
- simpler). vfnprintf returns the actual number of characters
- output or -1 in case of error.
-
- And yes, there is also a fnprintf():
-
- int fnprintf(_vfn fn, void * st, const char * format, ...);
-
- -- Bakul Shah <bvs@BitBlocks.com>
-
- PS: Note that floating point formats are not yet handled. But
- vfnprintf does accept all the rest of the ANSI format chars.
-