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