00001 #ifndef S11N_NET_VAPPENDF_H_INCLUDED_ 00002 #define S11N_NET_VAPPENDF_H_INCLUDED_ 1 00003 #include <stdarg.h> 00004 #include <ostream> 00005 namespace s11n { 00006 00007 /** 00008 This code implements a printf-like implementation which supports 00009 aribtrary data destinations. 00010 00011 Authors: many, probably. This code supposedly goes back to the 00012 early 1980's. 00013 00014 License: Public Domain. 00015 */ 00016 00017 /** 00018 The vappendf_appender typedef is used to provide vappendf() 00019 with a flexible output routine, so that it can be easily 00020 send its output to arbitrary targets. 00021 00022 The policies which implementations need to follow are: 00023 00024 - arg is an implementation-specific pointer (may be 0) which is 00025 passed to vappendf. vappendf() doesn't know what this argument is 00026 but passes it to its vappendf_appender. Typically it will be an 00027 object or resource handle to which string data is pushed or output. 00028 00029 - The 'data' parameter is the data to append. If it contains 00030 embedded nulls, this function will stop at the first one. Thus 00031 it is not binary-safe. 00032 00033 - n is the number of bytes to read from data. If n<0 then 00034 strlen(data) should be used. 00035 00036 - Returns, on success, the number of bytes appended (may be 0). 00037 00038 - Returns, on error, an implementation-specified negative number. 00039 Returning a negative error code will cause vappendf() to stop the 00040 processing of that string. Note that 0 is a success value (some 00041 printf format specifiers do not add anything to the output). 00042 */ 00043 typedef long (*vappendf_appender)( void * arg, 00044 char const * data, 00045 long n ); 00046 00047 00048 /* 00049 This function works similarly to classical printf implementations, 00050 but instead of outputing somewhere specific, it uses a callback 00051 function to push its output somewhere. This allows it to be used for 00052 arbitrary external representations. It can be used, for example, to 00053 output to an external string, a UI widget, or file handle (it can 00054 also emulate printf by outputing to stdout this way). 00055 00056 INPUTS: 00057 00058 pfAppend : The is a vappendf_appender function which is responsible 00059 for accumulating the output. If pfAppend returns a negative integer 00060 then processing stops immediately. 00061 00062 pfAppendArg : is ignored by this function but passed as the first 00063 argument to pfAppend. pfAppend will presumably use it as a data 00064 store for accumulating its string. 00065 00066 fmt : This is the format string, as in the usual printf(). 00067 00068 ap : This is a pointer to a list of arguments. Same as in 00069 vprintf() and friends. 00070 00071 00072 OUTPUTS: 00073 00074 The return value is the total number of characters sent to the 00075 function "func", or a negative number on a pre-output error. If this 00076 function returns an integer greater than 1 it is in general 00077 impossible to know if all of the elements were output. As such 00078 failure can only happen if the callback function returns an error, 00079 and this type of error is very rare in a printf-like context, this is 00080 not considered to be a significant problem. (The same is true for any 00081 classical printf implementations, as far as i'm aware.) 00082 00083 00084 CURRENT (documented) PRINTF EXTENSIONS: 00085 00086 %z works like %s, but takes a non-const (char *) in the va_list, and 00087 vappendf deletes the string (using free()) after appending it to the 00088 output. 00089 00090 %h (HTML) works like %s but converts certain characters (like '<' and '&' to 00091 their HTML escaped equivalents. 00092 00093 %t (URL encode) works like %s but converts certain characters into a representation 00094 suitable for use in an HTTP URL. (e.g. ' ' gets converted to %20) 00095 00096 %T (URL decode) does the opposite of %t - it decodes URL-encoded 00097 strings. 00098 00099 %n requires an (int*) in the va_list, which gets assigned 00100 the number of bytes this function has appended to cb so far. 00101 00102 %r requires an int and renders it in "ordinal form". That is, 00103 the number 1 converts to "1st" and 398 converts to "398th". 00104 00105 %q quotes a string as required for SQL. That is, '\'' characters get doubled. 00106 00107 %Q as %q, but includes the outer '\'' characters and null pointers 00108 replaced by SQL NULL. 00109 00110 (The %q and %Q specifiers are options inherited from this printf 00111 implementation's sqlite3 genes.) 00112 00113 */ 00114 long vappendf( 00115 vappendf_appender pfAppend, /* Accumulate results here */ 00116 void * pfAppendArg, /* Passed as first arg to pfAppend. */ 00117 const char *fmt, /* Format string */ 00118 va_list ap /* arguments */ 00119 ); 00120 00121 /** 00122 Identical to vappendf() but does not take a va_list. 00123 */ 00124 long appendf(vappendf_appender pfAppend, 00125 void * pfAppendArg, 00126 const char *fmt, 00127 ... ); 00128 00129 /** 00130 An overload which sends its output to the given ostream. 00131 */ 00132 long vappendf( std::ostream & target, 00133 const char *fmt, 00134 va_list ap 00135 ); 00136 00137 /** 00138 An overload which sends its output to the given ostream. 00139 */ 00140 long appendf( std::ostream & target, 00141 const char *fmt, 00142 ... ); 00143 00144 } /* extern "C" || namespace */ 00145 #endif // S11N_NET_VAPPENDF_H_INCLUDED_