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