1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup format C-string formatting
36  *  @ingroup dnscore
37  *  @brief
38  *
39  * @{
40  *
41  *----------------------------------------------------------------------------*/
42 
43 #pragma once
44 
45 #include <stdio.h>
46 #include <stdarg.h>
47 
48 #include <dnscore/sys_types.h>
49 #include <dnscore/output_stream.h>
50 #include <dnscore/dnscore.h>
51 
52 #define OSPRINT_DUMP_LAYOUT_GROUP_MASK      0x0000ff00U
53 #define OSPRINT_DUMP_LAYOUT_GROUP_SHIFT     0x00000008U
54 #define OSPRINT_DUMP_LAYOUT_SEPARATOR_MASK  0x000000ffU
55 #define OSPRINT_DUMP_LAYOUT_SEPARATOR_SHIFT 0x00000000U
56 #define OSPRINT_DUMP_OFFSET                 0x80000000U
57 #define OSPRINT_DUMP_ADDRESS                0x40000000U
58 #define OSPRINT_DUMP_HEX                    0x20000000U
59 #define OSPRINT_DUMP_TEXT                   0x10000000U
60 #define OSPRINT_DUMP_SQUEEZE_ZEROES         0x08000000U
61 
62 // predefined layouts
63 #define OSPRINT_DUMP_LAYOUT_DENSE           0x0000ffffU
64 #define OSPRINT_DUMP_LAYOUT_ERIC            0x000003ffU
65 #define OSPRINT_DUMP_LAYOUT_GERY            0x00000003U
66 
67 #define OSPRINT_DUMP_ALL                    (OSPRINT_DUMP_ADDRESS|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT)
68 #define OSPRINT_DUMP_BUFFER                 (OSPRINT_DUMP_OFFSET|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT)
69 #define OSPRINT_DUMP_HEXTEXT                (OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT)
70 #define OSPRINT_DUMP_BASE16                 (OSPRINT_DUMP_LAYOUT_DENSE|OSPRINT_DUMP_HEX)
71 
72 /**
73  *
74  * Formats:
75  *
76  *   modifier   : restrict :
77  *              :    to    :
78  * -            :          : change justification
79  * 123456789    :          : padding space
80  * 0            :          : use '0' char for padding
81  * .12345789    : f        : for float types, precision to use
82  * hh           : iudXxo   : half half : 8 bits
83  * h            : iudXxo   : half : 16 bits
84  * l            : iudXxo   : long : 32 bits
85  * ll           : iudXxo   : long long : 64 bits
86  * L            : f        : long double
87  *
88  *    formats   :
89  *              :
90  * %t           : integer, prints the number of tabs on the output
91  * %S           : integer, prints the number of spaces on the output
92  * %T           : integer, prints the 32/64 bits UTC time on the output
93  *                %T   : 32 bits = YYYY-MM-DD HH:mm:SS
94  *                %lT  : 64 bits = YYYY-MM-DD HH:mm:SS
95  *                %llT : 64 bits = YYYY-MM-DD HH:mm:SS.NNNNNN
96  * %i           : integer, prints the signed 8/16/32/64 bits integer in base 10 on the output
97  * %r           : integer, prints the ya_result registered message on the output or the hexadecimal code
98  * %u           : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output
99  * %d           : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output
100  * %X           : integer, prints the unsigned 8/16/32/64 bits integer in base 16 uppercase on the output
101  * %x           : integer, prints the unsigned 8/16/32/64 bits integer in base 16 lowercase on the output
102  * %o           : integer, prints the unsigned 8/16/32/64 bits integer in base 8 on the output
103  * %p           : void*  , prints the pointer in hexadecimal on the output
104  * %P           : void*  , prints the name of the pointer if possible, else the hexadecimal on the output
105  * %f           : double , prints the long double/double/float on the output
106  * %s           : char*  , prints the ASCIIZ string on the output
107  * %c           : char   , prints the 8-bits char on the output
108  * %w           : format_writer, calls the format_writer callback to print on the output
109  *
110  * Format extension mechanism:
111  *
112  * "%{registeredformatname}" : void*, prints the pointed value on the output
113  *                           : use ya_result format_registerclass(format_handler_descriptor* fhd) for registration
114  */
115 
116 /* void* value, output_stream*, s32 padding, char pad_char, bool left_justified, void* reserved */
117 
118 typedef void format_handler_method(const void*, output_stream*, s32, char, bool, void* reserved_for_method_parameters);
119 
120 typedef struct format_handler_descriptor format_handler_descriptor;
121 
122 // About the %w format:
123 //
124 // a pointer to this can be given as a 'w' parameter ie: "%w"
125 // the writer callback get's called with
126 // void* value as first parameter, what to print
127 // output_stream *os as second parameter, where to write the chars to
128 // s32 padding the number of chars it's supposed to take on the output (minimum)
129 // char padchar the character to use for padding
130 // bool left_justified where to justify the text
131 // void* don't use that one
132 //
133 // ex:
134 //
135 // format_writer temp_fw_0 = {my_complex_or_rare_type_printer_callback, &my_complex_or_rare_type};
136 //
137 // format("So the value is : '%w'\n", &temp_fw_0);
138 //
139 
140 struct format_writer
141 {
142     format_handler_method *callback;
143     const void * value;
144 };
145 
146 typedef struct format_writer format_writer;
147 
148 struct format_handler_descriptor
149 {
150     const char* name;
151     int name_len;	    /* Needed in order to quicken the matching */
152     format_handler_method* format_handler;
153 };
154 
155 void format_class_init();
156 
157 ya_result format_registerclass(const format_handler_descriptor* fhd);
158 
159 /**
160  * %% -> %
161  * %-09lli right-justified 0-padded "long long integer" (s64)
162  * %-9llu right-justified "long long unsigned integer" (u64)
163  * %-20{class} right-justified "class" (class has to be registered)
164  * %-20{class(a,b,c,d)} right-justified "class" called with 4 arguments (class has to be registered)
165  *
166  * %[-][0| ]([hh|h|l|ll]u|i|x)|([L]f)|c|s|{}
167  *
168  * ---
169  *
170  * hh  8 bits
171  * h  16 bits
172  * l  32 bits (The default if no length is given is 32 bits)
173  * ll 64 bits
174  *
175  * i signed integer
176  * u unsigned integer
177  * d unsigned integer
178  * x hexadecimal lo
179  * X hexadecimal hi
180  * b binary (not in yet)
181  *
182  * ---
183  *
184  * L long
185  *
186  * f double
187  *
188  * ---
189  *
190  * c char
191  *
192  * ---
193  *
194  * s asciiz string
195  *
196  * ---
197  *
198  * {class name} pointer to something that will be interpreted by the handler
199  *
200  */
201 
202 ya_result vosformat(output_stream* os_, const char* fmt, va_list args);
203 ya_result osprint(output_stream* stream,const char* text);
204 ya_result osprintln(output_stream* stream,const char* text);
205 ya_result osformat(output_stream* stream,const char* fmt,...);
206 ya_result osformatln(output_stream* stream,const char* fmt,...);
207 ya_result print(const char* text);
208 ya_result println(const char* text);
209 ya_result format(const char* fmt,...);
210 ya_result formatln(const char* fmt,...);
211 
212 // prefixes time | pid | pthread_self
213 ya_result debug_osformatln(output_stream* stream, const char* fmt, ...);
214 ya_result debug_println(const char* text);
215 
216 int vsnformat(char* out_, size_t out_size, const char* fmt, va_list args);
217 int snformat(char* out, size_t out_size, const char* fmt, ...);
218 
219 /**
220  * This formatter will return an allocated (malloc) string as a result of the format
221  *
222  * @param outp
223  * @param out_size
224  * @param fmt
225  * @param args
226  * @return
227  */
228 
229 int vasnformat(char** outp, size_t out_size, const char* fmt, va_list args);
230 
231 /**
232  * This formatter will return an allocated (malloc) string as a result of the format
233  *
234  * @param outp
235  * @param out_size
236  * @param fmt
237  * @param ...
238  * @return
239  */
240 
241 int asnformat(char** outp, size_t out_size, const char* fmt, ...);
242 
243 /**
244  * This formatter will return an allocated (malloc) string as a result of the format
245  *
246  * @param outp
247  * @param fmt
248  * @param ...
249  * @return
250  */
251 
252 int asformat(char** outp, const char* fmt, ...);
253 
254 /* Used by extensions */
255 
256 void format_dec_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
257 void format_dec_s64(s64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
258 void format_hex_u64_lo(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
259 void format_hex_u64_hi(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
260 void format_oct_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
261 void format_asciiz(const char* val, output_stream* stream, s32 padding, char pad_char, bool left_justified);
262 
263 /**/
264 
265 int osprint_base16(output_stream* os, const u8* rdata, u32 rdata_size);
266 int osprint_base64(output_stream* os, const u8* rdata, u32 rdata_size);
267 
268 void osprint_u32(output_stream* os, u32 value);
269 void osprint_u16(output_stream* os, u16 value);
270 void osprint_u32_hex(output_stream* os, u32 value);
271 
272 void print_char(char value);
273 
274 void osprint_char(output_stream *os, char value);
275 void osprint_char_times(output_stream *os, char value, int times);
276 void osprint_dump_with_base(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags, const void* base_pointer_);
277 void osprint_dump(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags);
278 
279 ya_result osprint_type_bitmap(output_stream *os, const u8 *rdata_pointer, u16 rdata_size);
280 ya_result osprint_rdata(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size);
281 ya_result osprint_rdata_escaped(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size);
282 ya_result print_rdata(u16 type, u8 *rdata, u16 rdata_size);
283 
284 void osprint_question(output_stream *os, u8 *qname, u16 qclass, u16 qtype);
285 void print_question(u8 *qname, u16 qclass, u16 qtype);
286 
287 #if 0 /* fix */
288 #else
289 #define FORMAT_BREAK_ON_INVALID(address__, len__)
290 #endif
291 
292 /*
293  * This is just a tool function used to test vsnformat.
294  * It is not meant for the logger.
295  * It has an output length limitation of 4096 bytes.
296  *
297  * Please use the other functions if possible.
298  */
299 
300 int fformat(FILE *out, const char *fmt, ...);
301 
302 /**
303  * This tool struct is used so the RDATA part of a record can be printed/formatted
304  *
305  * we would have:
306  *
307  * rdata_desc myrdata={TYPE_SOA, rdata_len, rdata};
308  * format("bla bla bla %{rdatadesc}", &myrdata);
309  *
310  *
311  */
312 
313 struct rdata_desc_s
314 {
315     u16         type;
316     u16         len;
317     const u8 *  rdata;
318 };
319 
320 typedef struct rdata_desc_s rdata_desc;
321 
322