dprintf.hpp

    1: #ifndef DPRINTF_HPP
    2: #define DPRINTF_HPP
    3: /*------------------------------------------------------------------------------
    4: 
    5:   Author:    Andy Rushton
    6:   Copyright: (c) Andy Rushton, 2004
    7:   License:   BSD License, see ../docs/license.html
    8: 
    9:   Provides an sprintf-like function acting on STL strings. The 'd' in dprintf
   10:   stands for "dynamic" in that the string is a dynamic string whereas a char*
   11:   buffer would be static (in size that is, not static in C terms).
   12: 
   13:   I have chosen to partially re-invent the wheel here. This is because the
   14:   obvious solution to the problem of in-memory formatted output is to use
   15:   sprintf(), but this is a potentially dangerous operation since it will quite
   16:   happily charge off the end of the string it is printing to and thereby
   17:   corrupt memory. This kind of buffer-overflow vulnerability is the source of
   18:   most security failures exploited by virus-writers. It means that sprintf
   19:   should never be used and should be made obsolete.
   20: 
   21:   In any case, using arbitrary-sized fixed-length buffers is not part of any
   22:   quality-orientated design philosophy.
   23: 
   24:   I would like to make this set of functions obsolete too, since I believe the
   25:   C runtime should be deprecated in favour of C++ runtime which uses dynamic
   26:   strings and can handle exceptions. However, there is as yet no C++
   27:   equivalent functionality to some of the string-handling available through
   28:   the printf-like functions, so it has to stay for now.
   29: 
   30: int dprintf (std::string& buffer, const char* format, ...);
   31: 
   32:    Like sprintf(), formats the message by appending to the std::string buffer
   33:    according to the formatting codes in the format string. The return int is
   34:    the number of characters generated by this call, i.e. the increase in the
   35:    length of the std::string.
   36: 
   37: int vdprintf (std::string& buffer, const char* format, va_list args);
   38: 
   39:    As above, but using a pre-initialised va_args argument list. Useful for nesting
   40:    dprintf calls within variable argument functions.
   41: 
   42: std::string dformat (const char* format, ...);
   43: 
   44:    Similar to dprintf() above, except the result is formatted into a new std::string
   45:    which is returned by the function. Very useful for inline calls within a textio
   46:    expression.
   47:    e.g.    fout << "Total: " << sformat("%6i",t) << newline;
   48: 
   49: std::string vdformat (const char* format, va_list);
   50: 
   51:    As above, but using a pre-initialised va_args argument list. Useful for nesting
   52:    dformat calls within variable argument functions.
   53: 
   54: The format string supports the following format codes as in the C runtime library:
   55: 
   56:    % [ flags ] [ field ] [ . precision ] [ modifier ] [ conversion ]
   57: 
   58:  flags:
   59:    -    - left justified
   60:    +    - print sign for +ve numbers
   61:    ' '  - leading space where + sign would be
   62:    0    - leading zeros to width of field
   63:    #    - alternate format
   64: 
   65:  field:
   66:    a numeric argument specifying the field width - default = 0
   67:    * means take the next va_arg as the field width - if negative then left justify
   68: 
   69:  precision:
   70:    a numeric argument the meaning of which depends on the conversion -
   71:    - %s - max characters from a string - default = strlen()
   72:    - %e, %f - decimal places to be displayed - default = 6
   73:    - %g - significant digits to be displayed - default = 6
   74:    - all integer conversions - minimum digits to display - default = 0
   75:    * means take the next va_arg as the field width - if negative then left justify
   76: 
   77:  modifier:
   78:    h    - short or unsigned short
   79:    l    - long or unsigned long
   80:    L    - long double
   81:    
   82:  conversions:
   83:    d, i - short/int/long as decimal
   84:    u    - short/int/long as unsigned decimal
   85:    o    - short/int/long as unsigned octal - # adds leading 0
   86:    x, X - short/int/long as unsigned hexadecimal - # adds leading 0x
   87:    c    - char
   88:    s    - char*
   89:    C    - wchar_t
   90:    S    - wchar_t*
   91:    f    - double/long double as fixed point
   92:    e, E - double/long double as floating point
   93:    g, G - double/long double as fixed point/floating point depending on value
   94:    p    - void* as unsigned hexadecimal
   95:    %    - literal %
   96:    n    - int* as recipient of length of formatted string so far
   97: 
   98: ------------------------------------------------------------------------------*/
   99: #include "os_fixes.hpp"
  100: #include <string>
  101: #include <stdexcept>
  102: #include <stdarg.h>
  103: 
  104: // format by appending to a string and return the increase in length
  105: // if there is an error, return a negative number and leave the string unchanged
  106: int dprintf (std::string& formatted, const char* format, ...);
  107: int vdprintf (std::string& formatted, const char* format, va_list args);
  108: 
  109: // format into a new string and return the result
  110: // if there is an error, throw an exception
  111: std::string dformat (const char* format, ...) throw(std::invalid_argument);
  112: std::string vdformat (const char* format, va_list) throw(std::invalid_argument);
  113: 
  114: #endif