home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / c / 11406 < prev    next >
Encoding:
Text File  |  1992-07-21  |  3.5 KB  |  106 lines

  1. 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
  2. From: bvs@BitBlocks.COM (Bakul Shah)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: (Help) dynamic use of sprintf ?
  5. Message-ID: <1992Jul21.201712.20985@BitBlocks.COM>
  6. Date: 21 Jul 92 20:17:12 GMT
  7. References: <brself.711345285@hal>
  8. Organization: Bit Blocks, Inc.
  9. Lines: 95
  10.  
  11. brself@hal.gnu.ai.mit.edu (Ben Self) writes:
  12. > Could anyone please help me with a C programming dilemma that has plagued me
  13. > for ages.
  14. > Often when formatting strings or converting numerics to alphas, sprintf ()
  15. > appears as an extremely attractive possibility.  Unfortunately, it does not
  16. > fit well with dynamic allocation nor is it easily safe guarded from 
  17. > segmentation faults and bus errors.
  18.    ...
  19. > We must sell -- any serious offer will be accepted :-)
  20. > Thanks in advance.
  21.  
  22. Here is another solution that will work for this and many other
  23. formatting uses.  PD source code on request.
  24.  
  25. I have a vfprintf like function, called `vfnprintf' that takes a
  26. _function pointer_ instead of a FILE *.  vfnprintf calls this
  27. function, possibly multiple times, to drain already formatted
  28. characters.  _You_ supply the function.  Here is an example use.
  29.  
  30.   #include <stdarg.h>
  31.  
  32.   struct snstate {
  33.       int    size;
  34.       int    offset;
  35.       char *    buffer;
  36.   };
  37.  
  38.   /* typedef for a function ptr */
  39.   typedef int (*_vfn_t)(void * st, const char * string, unsigned int count);
  40.  
  41.   int vfnprintf(_vfn_t fn, void * st, const char * format, va_list args);
  42.  
  43.   /*
  44.    * a function to drain the formatted chars
  45.    * It doesn't allow a write beyond the
  46.    * end of st->bufer and nul terminates
  47.    * the copied string.
  48.    */
  49.   int sndrain(struct snstate * st, char * str, int count) {
  50.       int space = st->size - st->offset - 1;
  51.       if (count > space)
  52.           count = space;
  53.       if (count > 0) {
  54.           memcpy(st->buffer + st->offset, str, count);
  55.           st->offset += count;
  56.           st->buffer[st->offset] = '\0';
  57.       }
  58.       return count;
  59.   }
  60.  
  61.   /*
  62.    * given sndrain and vfnprintf, snprintf can be defined to
  63.    * to `sprintf' to a string of given size
  64.    */
  65.   int snprintf(char * str, int size, const char * fmt, ...) {
  66.       int count;
  67.       va_list args;
  68.       struct snstate snstate;
  69.       snstate.size = size;
  70.       snstate.offset = 0;
  71.       snstate.buffer = str;
  72.  
  73.       va_start(args, fmt);
  74.       count = vfnprintf((_vfn_t)sndrain, &snstate, fmt, args);
  75.       va_end(args);
  76.       return count;
  77.   }
  78.  
  79. You can equally easily provide another function that allocates
  80. more space as needed.  Since the function ptr arg to vfnprintf
  81. takes a ptr to a `state' struct, you can even collect the output
  82. from multiple snprintf calls.  (And if snstate->buffer mmap()ed
  83. to some file then who needs stdio!  But I digress.)  vfnprintf is
  84. low level enough that stdio can be built atop it though you
  85. probably wouldn't want to do so for performance reasons.
  86.  
  87. vfnprintf will call `fn' whenever it wants to output one or more
  88. formatted chars. Function `fn' should return the number of chars
  89. it could drain, 0 if none and -1 to indicate an error.  It can
  90. keep any needed state in `st' (unfortunately, C doesn't have
  91. nested functions or else the vfnprintf interface would've been
  92. simpler).  vfnprintf returns the actual number of characters
  93. output or -1 in case of error.
  94.  
  95. And yes, there is also a fnprintf():
  96.  
  97.   int fnprintf(_vfn fn, void * st, const char * format, ...);
  98.  
  99. -- Bakul Shah <bvs@BitBlocks.com>
  100.  
  101. PS: Note that floating point formats are not yet handled.  But
  102.     vfnprintf does accept all the rest of the ANSI format chars.
  103.