Add support for '+' in custom format specifiers
[strongswan.git] / src / libstrongswan / printf_hook.h
1 /*
2 * Copyright (C) 2009 Tobias Brunner
3 * Copyright (C) 2006-2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 /**
18 * @defgroup printf_hook printf_hook
19 * @{ @ingroup libstrongswan
20 */
21
22 #ifndef PRINTF_HOOK_H_
23 #define PRINTF_HOOK_H_
24
25 typedef struct printf_hook_t printf_hook_t;
26 typedef struct printf_hook_spec_t printf_hook_spec_t;
27 typedef struct printf_hook_data_t printf_hook_data_t;
28 typedef enum printf_hook_argtype_t printf_hook_argtype_t;
29
30 #if !defined(USE_VSTR) && \
31 !defined(HAVE_PRINTF_FUNCTION) && \
32 !defined(HAVE_PRINTF_SPECIFIER)
33 /* assume newer glibc register_printf_specifier if none given */
34 #define HAVE_PRINTF_SPECIFIER
35 #endif
36
37 #if !defined(USE_VSTR) && \
38 (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
39
40 #include <stdio.h>
41 #include <printf.h>
42
43 enum printf_hook_argtype_t {
44 PRINTF_HOOK_ARGTYPE_END = -1,
45 PRINTF_HOOK_ARGTYPE_INT = PA_INT,
46 PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER,
47 };
48
49 /**
50 * Data to pass to a printf hook.
51 */
52 struct printf_hook_data_t {
53
54 /**
55 * Output FILE stream
56 */
57 FILE *stream;;
58 };
59
60 /**
61 * Helper macro to be used in printf hook callbacks.
62 */
63 #define print_in_hook(data, fmt, ...) ({\
64 int _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\
65 if (_written < 0)\
66 {\
67 _written = 0;\
68 }\
69 _written;\
70 })
71
72 #else
73
74 #include <vstr.h>
75
76 enum printf_hook_argtype_t {
77 PRINTF_HOOK_ARGTYPE_END = VSTR_TYPE_FMT_END,
78 PRINTF_HOOK_ARGTYPE_INT = VSTR_TYPE_FMT_INT,
79 PRINTF_HOOK_ARGTYPE_POINTER = VSTR_TYPE_FMT_PTR_VOID,
80 };
81
82 /**
83 * Redefining printf and alike
84 */
85 #include <stdio.h>
86 #include <stdarg.h>
87
88 int vstr_wrapper_printf(const char *format, ...);
89 int vstr_wrapper_fprintf(FILE *stream, const char *format, ...);
90 int vstr_wrapper_sprintf(char *str, const char *format, ...);
91 int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...);
92 int vstr_wrapper_asprintf(char **str, const char *format, ...);
93
94 int vstr_wrapper_vprintf(const char *format, va_list ap);
95 int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap);
96 int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
97 int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
98 int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
99
100 #define printf vstr_wrapper_printf
101 #define fprintf vstr_wrapper_fprintf
102 #define sprintf vstr_wrapper_sprintf
103 #define snprintf vstr_wrapper_snprintf
104 #define asprintf vstr_wrapper_asprintf
105
106 #define vprintf vstr_wrapper_vprintf
107 #define vfprintf vstr_wrapper_vfprintf
108 #define vsprintf vstr_wrapper_vsprintf
109 #define vsnprintf vstr_wrapper_vsnprintf
110 #define vasprintf vstr_wrapper_vasprintf
111
112 /**
113 * Data to pass to a printf hook.
114 */
115 struct printf_hook_data_t {
116
117 /**
118 * Base to append printf to
119 */
120 Vstr_base *base;
121
122 /**
123 * Position in base to write to
124 */
125 size_t pos;
126 };
127
128 /**
129 * Helper macro to be used in printf hook callbacks.
130 */
131 #define print_in_hook(data, fmt, ...) ({\
132 int _written = vstr_add_fmt(data->base, data->pos, fmt, ##__VA_ARGS__);\
133 data->pos += _written;\
134 _written;\
135 })
136
137 #endif
138
139 /**
140 * Callback function type for printf hooks.
141 *
142 * @param data hook data, to pass to print_in_hook()
143 * @param spec format specifier
144 * @param args arguments array
145 * @return number of characters written
146 */
147 typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
148 printf_hook_spec_t *spec,
149 const void *const *args);
150
151 /**
152 * Properties of the format specifier
153 */
154 struct printf_hook_spec_t {
155 /**
156 * TRUE if a '#' was used in the format specifier
157 */
158 int hash;
159
160 /**
161 * TRUE if a '-' was used in the format specifier
162 */
163 int minus;
164
165 /**
166 * TRUE if a '+' was used in the format specifier
167 */
168 int plus;
169
170 /**
171 * The width as given in the format specifier.
172 */
173 int width;
174 };
175
176 /**
177 * Printf handler management.
178 */
179 struct printf_hook_t {
180
181 /**
182 * Register a printf handler.
183 *
184 * @param spec printf hook format character
185 * @param hook hook function
186 * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END
187 */
188 void (*add_handler)(printf_hook_t *this, char spec,
189 printf_hook_function_t hook, ...);
190
191 /**
192 * Destroy a printf_hook instance.
193 */
194 void (*destroy)(printf_hook_t *this);
195 };
196
197 /**
198 * Create a printf_hook instance.
199 */
200 printf_hook_t *printf_hook_create();
201
202 #endif /** PRINTF_HOOK_H_ @}*/